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 号自定义过滤器。
我在 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 号自定义过滤器。