Spring Security笔记自定义LoginLogout FilterAuthenticationProvider+++.docx
《Spring Security笔记自定义LoginLogout FilterAuthenticationProvider+++.docx》由会员分享,可在线阅读,更多相关《Spring Security笔记自定义LoginLogout FilterAuthenticationProvider+++.docx(28页珍藏版)》请在冰豆网上搜索。
SpringSecurity笔记自定义LoginLogoutFilterAuthenticationProvider+++
SpringSecurity笔记:
自定义Login/LogoutFilter、AuthenticationProviderauto-config Automaticallyregistersaloginform,BASICauthentication,logoutservices.Ifsetto"true",allofthesecapabilitiesareadded(althoughyoucanstillcustomizetheconfigurationofeachbyprovidingtherespectiveelement).
------------------
可以理解为:
1<>
2
3<-basic/>
4
5>
下面是SpringSecurityFilterChain的列表:
Table1.StandardFilterAliasesandOrdering
Alias
FilterClass
NamespaceElementorAttribute
CHANNEL_FILTER
ChannelProcessingFilter
/intercept-url@requires-channel
SECURITY_CONTEXT_FILTER
SecurityContextPersistenceFilter
CONCURRENT_SESSION_FILTER
ConcurrentSessionFilter
session-management/concurrency-control
HEADERS_FILTER
HeaderWriterFilter
/headers
CSRF_FILTER
CsrfFilter
/csrf
LOGOUT_FILTER
LogoutFilter
/logout
X509_FILTER
X509AuthenticationFilter
/x509
PRE_AUTH_FILTER
AstractPreAuthenticatedProcessingFilter Subclasses
N/A
CAS_FILTER
CasAuthenticationFilter
N/A
FORM_LOGIN_FILTER
UsernamePasswordAuthenticationFilter
/form-login
BASIC_AUTH_FILTER
BasicAuthenticationFilter
/-basic
SERVLET_API_SUPPORT_FILTER
SecurityContextHolderAwareRequestFilter
/@servlet-api-provision
JAAS_API_SUPPORT_FILTER
JaasApiIntegrationFilter
/@jaas-api-provision
REMEMBER_ME_FILTER
RememberMeAuthenticationFilter
/remember-me
ANONYMOUS_FILTER
AnonymousAuthenticationFilter
/anonymous
SESSION_MANAGEMENT_FILTER
SessionManagementFilter
session-management
EXCEPTION_TRANSLATION_FILTER
ExceptionTranslationFilter
FILTER_SECURITY_INTERCEPTOR
FilterSecurityInterceptor
SWITCH_USER_FILTER
SwitchUserFilter
N/A
其中红色标出的二个Filter对应的是“注销、登录”,如果不使用auto-config=true,开发人员可以自行“重写”这二个Filter来达到类似的目的,比如:
默认情况下,登录表单必须使用post方式提交,在一些安全性相对不那么高的场景中(比如:
企业内网应用),如果希望通过类似:
//xxx/login?
username=abc&password=123的方式直接登录,可以参考下面的代码:
1packageblogs.yjmyzz;
2
3importjavax.servlet..ServletRequest;
4importjavax.servlet..ServletResponse;
5
6//importorg.springframework.security.authentication.AuthenticationServiceException;
7importorg.springframework.security.authentication.UsernamePasswordAuthenticationToken;
8importorg.springframework.security.core.Authentication;
9importorg.springframework.security.core.AuthenticationException;
10importorg.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
11
12publicclassCustomLoginFilterextendsUsernamePasswordAuthenticationFilter{
13
14publicAuthenticationattemptAuthentication(ServletRequestrequest,
15ServletResponseresponse)throwsAuthenticationException{
16
17//if(!
request.getMethod().equals("POST")){
18//thrownewAuthenticationServiceException(
19//"Authenticationmethodnotsupported:
"
20//+request.getMethod());
21//}
22
23Stringusername=obtainUsername(request).toUpperCase().trim();
24Stringpassword=obtainPassword(request);
25
26UsernamePasswordAuthenticationTokenauthRequest=newUsernamePasswordAuthenticationToken(
27username,password);
28
29setDetails(request,authRequest);
30returnthis.getAuthenticationManager().authenticate(authRequest);
31}
32
33}
即:
从UsernamePasswordAuthenticationFilter继承一个类,然后把关于POST方式判断的代码注释掉即可。
默认情况下,SpringSecurity的用户名是区分大小写,如果觉得没必要,上面的代码同时还演示了如何在Filter中自动将其转换成大写。
默认情况下,登录成功后,SpringSecurity有自己的handler处理类,如果想在登录成功后,加一点自己的处理逻辑,可参考下面的代码:
1packageblogs.yjmyzz;
2
3importjava.io.IOException;
4
5importjavax.servlet.ServletException;
6importjavax.servlet..ServletRequest;
7importjavax.servlet..ServletResponse;
8
9importorg.springframework.security.core.Authentication;
10importorg.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
11
12publicclassCustomLoginHandlerextends
13SavedRequestAwareAuthenticationSuccessHandler{
14
15@Override
16publicvoidonAuthenticationSuccess(ServletRequestrequest,
17ServletResponseresponse,Authenticationauthentication)
18throwsServletException,IOException{
19super.onAuthenticationSuccess(request,response,authentication);
20
21//这里可以追加开发人员自己的额外处理
22System.out
23.println("CustomLoginHandler.onAuthenticationSuccess()iscalled!
");
24}
25
26}
类似的,要自定义LogoutFilter,可参考下面的代码:
1packageblogs.yjmyzz;
2
3importorg.springframework.security.web.authentication.logout.LogoutFilter;
4importorg.springframework.security.web.authentication.logout.LogoutHandler;
5importorg.springframework.security.web.authentication.logout.LogoutSuccessHandler;
6
7publicclassCustomLogoutFilterextendsLogoutFilter{
8
9publicCustomLogoutFilter(StringlogoutSuccessUrl,LogoutHandler[]handlers){
10super(logoutSuccessUrl,handlers);
11}
12
13publicCustomLogoutFilter(LogoutSuccessHandlerlogoutSuccessHandler,
14LogoutHandler[]handlers){
15super(logoutSuccessHandler,handlers);
16}
17
18}
即:
从LogoutFilter继承一个类,如果还想在退出后加点自己的逻辑(比如注销后,清空额外的Cookie之类\记录退出时间、地点之类),可重写doFilter方法,但不建议这样,有更好的做法,自行定义logoutSuccessHandler,然后在运行时,通过构造函数注入即可。
下面是自定义退出成功处理的handler示例:
1packageblogs.yjmyzz;
2
3importjavax.servlet..ServletRequest;
4importjavax.servlet..ServletResponse;
5
6importorg.springframework.security.core.Authentication;
7importorg.springframework.security.web.authentication.logout.LogoutHandler;
8
9publicclassCustomLogoutHandlerimplementsLogoutHandler{
10
11publicCustomLogoutHandler(){
12}
13
14@Override
15publicvoidlogout(ServletRequestrequest,
16ServletResponseresponse,Authenticationauthentication){
17System.out.println("CustomLogoutSuccessHandler.logout()iscalled!
");
18
19}
20
21}
这二个Filter弄好后,剩下的就是改配置:
1beansxmlns=":
//.springframework.org/schema/security"
2xmlns:
beans=":
//.springframework.org/schema/beans"xmlns:
xsi=":
//.w3.org/2001/XMLSchema-instance"
3xsi:
schemaLocation=":
//.springframework.org/schema/beans
4:
//.springframework.org/schema/beans/spring-beans-3.0.xsd
5:
//.springframework.org/schema/security
6:
//.springframework.org/schema/security/spring-security-3.2.xsd">
7
8
9
--替换默认的LogoutFilter-->
10
11
--替换默认的LoginFilter-->
12
13
14>
15
16
17...
18
19
20beanid="loginEntryPoint"
21class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
22
--默认登录页的url-->
23constructor-argvalue="/login"/>
24
bean>
25
26beanid="customLoginFilter"class="blogs.yjmyzz.CustomLoginFilter">
27
--校验登录是否有效的虚拟url-->
28propertyname="filterProcessesUrl"value="/checklogin"/>
29propertyname="authenticationManager"ref="authenticationManager"/>
30propertyname="usernameParameter"value="username"/>
31propertyname="passwordParameter"value="password"/>
32propertyname="authenticationSuccessHandler">
33
--自定义登录成功后的处理handler-->
34beanclass="blogs.yjmyzz.CustomLoginHandler">
35
--登录成功后的默认url-->
36propertyname="defaultTargetUrl"value="/welcome"/>
37
bean>
38
property>
39propertyname="authenticationFailureHandler">
40bean
41class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
42
--登录失败后的默认Url-->
43propertyname="defaultFailureUrl"value="/login?
error"/>
44
bean>
45
property>
46
bean>
47
48beanid="customLogoutFilter"class="blogs.yjmyzz.CustomLogoutFilter">
49
--处理退出的虚拟url-->
50propertyname="filterProcessesUrl"value="/logout"/>
51
--退出处理成功后的默认显示url-->
52constructor-argindex="0"value="/login?
logout"/>
53constructor-argindex="1">
54
--退出成功后的handler列表-->
55array>
56beanid="securityContextLogoutHandler"
57class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
58
--加入了开发人员自定义的退出成功处理-->
59beanid="customLogoutSuccessHandler"class="blogs.yjmyzz.CustomLogoutHandler"/>
60
array>
61
constructor-arg>
62
bean>
63
64
beans>
用户输入“用户名、密码”,并点击完登录后,最终实现校验的是AuthenticationProvider,而且一个webApp中可以同时使用多个Provider,下面是一个自定义Provider的示例代码:
1packageblogs.yjmyzz;
2
3importjava.util.ArrayList;
4importjava.util.Arrays;
5importjava.util.Collection;
6
7importorg.springframework.security.authentication.UsernamePasswordAuthenticationToken;
8importorg.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
9importorg.springframework.security.core.AuthenticationException;
10importorg.springframework.security.core.GrantedAuthority;
11importorg.springframework.security.core.authority.SimpleGrantedAuthority;
12importorg.springframework.security.core.userdetails.User;
13importorg.springframework.security.core.userdetails.UserDetails;
14
15publicclassCustomAuthenticationProviderextends
16AbstractUserDetailsAuthenticationProvider{
17
18@Override
19protectedvoidadditionalAuthenticationChecks(UserDetailsuserDetails,
20UsernamePasswordAuthenticationTokenauthentication)
21throwsAuthenticationException{
22//如果想做点额外的检查,可以在这个方法里处理,校验不通时,直接抛异常即可
23System.out
24.println("CustomAuthenticationProvider.additionalAuthenticationChecks()iscalled!
");
25}
26
27@Override
28protectedUserDetailsretrieveU