Spring 安全性:自定义过滤器后预授权

Spring Security : Preauthorize after custom filter

我在 spring 安全性中创建了自己的身份验证自定义过滤器。

<security:custom-filter ref="restServicesFilter"  position="FIRST"/>

这里是全保-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:security="http://www.springframework.org/schema/security"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/mvc
                           http://www.springframework.org/schema/mvc/spring-mvc.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/jdbc 
                           http://www.springframework.org/schema/jdbc/spring-jdbc.xsd
                           http://www.springframework.org/schema/data/jpa
                           http://www.springframework.org/schema/data/jpa/spring-jpa.xsd
                           http://www.springframework.org/schema/security
                           http://www.springframework.org/schema/security/spring-security.xsd
                           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
                           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">



<security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled"></security:global-method-security>


<security:http auto-config="false" authentication-manager-ref="authenticationManager" entry-point-ref="restAuthenticationEntryPoint" create-session="stateless">
<!--stateless for rest   -->
<security:custom-filter ref="restServicesFilter"  position="FIRST"/>



<security:access-denied-handler error-page="/error"/>
<security:csrf/>

</security:http>


<bean id="restServicesFilter"
class="com.pocdb.security.RestUsernamePasswordAuthenticationFilter">
<property name="postOnly" value="false" />
<property name="authenticationManager" ref="authenticationManager" />
<property name="authenticationSuccessHandler" ref="restServicesSuccessHandler" />
</bean>
<bean id="restServicesSuccessHandler"
class="com.pocdb.security.RestAuthenticationSuccessHandler" />


    <security:authentication-manager id="authenticationManager">
  <security:authentication-provider>
   <security:jdbc-user-service data-source-ref="dataSource"

    users-by-username-query="select username,password, enabled from users where username=?"
    authorities-by-username-query="select username, role from user_roles where username =?" />
  </security:authentication-provider>
 </security:authentication-manager> 



</beans>

我也在使用 Spring Data Rest,我的存储库看起来像这样

@RepositoryRestResource
@PreAuthorize("hasRole('ROLE_ADMIN')")
public interface TaskRepository extends CrudRepository<Task, Serializable>{
}

注意预授权的使用。

我的入口点 class 看起来像这样:

@Component
public final class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {

    public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException) throws IOException {
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
    }

过滤器 Class 是:

public class RestUsernamePasswordAuthenticationFilter extends
        UsernamePasswordAuthenticationFilter {


    @Override
    protected boolean requiresAuthentication(HttpServletRequest request,
            HttpServletResponse response) {
        // TODO Auto-generated method stub

        boolean retVal = false;
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        if (username != null && password != null) {
            Authentication authResult = null;
            try {
                authResult = attemptAuthentication(request, response);
                if (authResult == null) {
                    retVal = false;
                }
            } catch (AuthenticationException failed) {
                System.out.println("FUCKED");

            try {
                retVal=false;
                unsuccessfulAuthentication(request, response, failed);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ServletException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }   


            }

            FilterChain chain = null;
            try {
                retVal=false;
                successfulAuthentication(request, response, chain, authResult);
                retVal=true;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ServletException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }





        }
        return retVal;
    }

}

SuccessHandler 看起来像

public class RestAuthenticationSuccessHandler implements AuthenticationSuccessHandler{

    public void onAuthenticationSuccess(HttpServletRequest request,
            HttpServletResponse response, Authentication authentication)
            throws IOException, ServletException {
            //DO NOTHING???/?// after this will it go to PRE AUTHORIZE?

        System.out.println("SUCCESS HANDLER ");

    }

我假设在点击具有所需角色的 GET url '/tasks?username?XXX&password=XXX' 之后,我也会获得授权并能够查看 json.

但是,在我的 SuccessHandler Class 之后没有打印任何日志,并且请求未获得授权。我的自定义处理程序似乎工作得非常好。但是 @PreAuthorize 似乎不起作用。 在浏览器上,我都没有看到错误页面: 也不是 401
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized"); 而是一个完全空白的页面。所需的页面是 json,它向我展示了数据库中存在的所有任务。

出了什么问题?

另外,我对EntryPoint的commence()方法了解较少class。 有人可以帮忙吗?

一次请求后的日志:请注意,日志打印了两次:,可能是因为我同时使用 applicationContext 和 webContext 创建了 bean,但这与 @PreProcessor

无关
01:52:16.796 [btpool0-2] DEBUG o.s.security.web.FilterChainProxy - /tasks?username=Dipanshu&password=dipanshu at position 1 of 8 in additional filter chain; firing Filter: 'RestUsernamePasswordAuthenticationFilter'
01:52:16.802 [btpool0-2] DEBUG o.s.s.authentication.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
01:52:16.811 [btpool0-2] DEBUG o.s.jdbc.core.JdbcTemplate - Executing prepared SQL query
01:52:16.811 [btpool0-2] DEBUG o.s.jdbc.core.JdbcTemplate - Executing prepared SQL statement [select username,password, enabled from users where username=?]
01:52:16.813 [btpool0-2] DEBUG o.s.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
01:52:16.813 [btpool0-2] DEBUG o.s.j.d.DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/zz]
01:52:16.856 [btpool0-2] DEBUG o.s.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
01:52:16.858 [btpool0-2] DEBUG o.s.jdbc.core.JdbcTemplate - Executing prepared SQL query
01:52:16.858 [btpool0-2] DEBUG o.s.jdbc.core.JdbcTemplate - Executing prepared SQL statement [select username, role from user_roles where username =?]
01:52:16.858 [btpool0-2] DEBUG o.s.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
01:52:16.858 [btpool0-2] DEBUG o.s.j.d.DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/zz]
01:52:16.863 [btpool0-2] DEBUG o.s.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
01:52:16.865 [btpool0-2] DEBUG c.p.s.RestUsernamePasswordAuthenticationFilter - Authentication success. Updating SecurityContextHolder to contain: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@f5a6249a: Principal: org.springframework.security.core.userdetails.User@ee7a3e8: Username: Dipanshu; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER
SUCCESS HANDLER 
01:52:16.866 [btpool0-2] DEBUG c.p.s.RestUsernamePasswordAuthenticationFilter - Request is to process authentication
01:52:16.866 [btpool0-2] DEBUG o.s.s.authentication.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
01:52:16.866 [btpool0-2] DEBUG o.s.jdbc.core.JdbcTemplate - Executing prepared SQL query
01:52:16.866 [btpool0-2] DEBUG o.s.jdbc.core.JdbcTemplate - Executing prepared SQL statement [select username,password, enabled from users where username=?]
01:52:16.866 [btpool0-2] DEBUG o.s.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
01:52:16.866 [btpool0-2] DEBUG o.s.j.d.DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/zz]
01:52:16.871 [btpool0-2] DEBUG o.s.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
01:52:16.871 [btpool0-2] DEBUG o.s.jdbc.core.JdbcTemplate - Executing prepared SQL query
01:52:16.871 [btpool0-2] DEBUG o.s.jdbc.core.JdbcTemplate - Executing prepared SQL statement [select username, role from user_roles where username =?]
01:52:16.871 [btpool0-2] DEBUG o.s.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource
01:52:16.871 [btpool0-2] DEBUG o.s.j.d.DriverManagerDataSource - Creating new JDBC DriverManager Connection to [jdbc:mysql://localhost:3306/zz]
01:52:16.876 [btpool0-2] DEBUG o.s.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
01:52:16.877 [btpool0-2] DEBUG c.p.s.RestUsernamePasswordAuthenticationFilter - Authentication success. Updating SecurityContextHolder to contain: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@f5a6249a: Principal: org.springframework.security.core.userdetails.User@ee7a3e8: Username: Dipanshu; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ADMIN, ROLE_USER
SUCCESS HANDLER 

停止这种无意义的行为,使用 HTTP 基本身份验证,然后添加您的 N 号自定义过滤器。