读书人

Spring Security3.1登陆证验 替换 use

发布时间: 2012-07-02 17:46:22 作者: rapoo

Spring Security3.1登陆验证 替换 usernamepasswordfilter

一、前言

????? 在上一篇http://blog.csdn.net/k10509806/archive/2011/04/28/6369131.aspx文章中,提到的MyUserDetailServiceImpl获取用户权限,在用户没有登陆的时候,Spring Security会让我们自动跳转到默认的登陆界面,但在实际应用绝大多数是用我们自己的登陆界面的,其中就包括一些我们自己的逻辑,比如验证码。所以本人又研究一下,终于摸清了一些如何配置自己的登陆界面的办法。在这里献丑了。

?

二、Spring Security的过滤器

??????通过DEBUG可以看到Spring Security的Filter的顺序

Security filter chain: [
? ConcurrentSessionFilter
? SecurityContextPersistenceFilter
? LogoutFilter
? MyUsernamePasswordAuthenticationFilter
? RequestCacheAwareFilter
? SecurityContextHolderAwareRequestFilter
? RememberMeAuthenticationFilter
? AnonymousAuthenticationFilter
? SessionManagementFilter
? ExceptionTranslationFilter
? MySecurityFilter
? FilterSecurityInterceptor
]

Spring Security的登陆验证用的就是MyUsernamePasswordAuthenticationFilter,所以要实现我们自己的验证,可以写一个类并继承MyUsernamePasswordAuthenticationFilter类,重写attemptAuthentication方法。

?

三、applicationContext-Security.xml配置

?

[xhtml]?view plaincopy
  1. <?xml?version="1.0"?encoding="UTF-8"?>??
  2. <beans:beans?xmlns="http://www.springframework.org/schema/security"??
  3. ????xmlns:beans="http://www.springframework.org/schema/beans"??
  4. ????xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"??
  5. ????xsi:schemaLocation="http://www.springframework.org/schema/beans?http://www.springframework.org/schema/beans/spring-beans-3.0.xsd??
  6. ????????????????????????http://www.springframework.org/schema/security?http://www.springframework.org/schema/security/spring-security-3.1.xsd">??
  7. ??????????????????????????
  8. ????<debug/>????????
  9. ????<http?pattern="/js/**"?security="none"/>??
  10. ????<http?pattern="/resource/**"?security="none"></http>??
  11. ????<http?pattern="/login.jsp"?security="none"/>??
  12. ??????
  13. ????<http?use-expressions="true"?entry-point-ref="authenticationProcessingFilterEntryPoint">??
  14. ????????<logout/>??
  15. ????????<!--?实现免登陆验证?-->??
  16. ????????<remember-me?/>??
  17. ????????<session-management?invalid-session-url="/timeout.jsp">??
  18. ????????????<concurrency-control?max-sessions="10"?error-if-maximum-exceeded="true"?/>??
  19. ????????</session-management>??
  20. ??????????
  21. ????????<custom-filter?ref="loginFilter"?position="FORM_LOGIN_FILTER"??/>??
  22. ????????<custom-filter?ref="securityFilter"?before="FILTER_SECURITY_INTERCEPTOR"/>??
  23. ????</http>??
  24. ??????
  25. ????<!--?登录验证器?-->??
  26. ????<beans:bean?id="loginFilter"??
  27. ????????class="com.huaxin.security.MyUsernamePasswordAuthenticationFilter">??
  28. ????????<!--?处理登录的action?-->??
  29. ????????<beans:property?name="filterProcessesUrl"?value="/j_spring_security_check"></beans:property>??
  30. ????????????????<!--?验证成功后的处理-->??
  31. ????????<beans:property?name="authenticationSuccessHandler"?ref="loginLogAuthenticationSuccessHandler"></beans:property>??
  32. ????????????????<!--?验证失败后的处理-->??
  33. ????????<beans:property?name="authenticationFailureHandler"?ref="simpleUrlAuthenticationFailureHandler"></beans:property>??
  34. ????????<beans:property?name="authenticationManager"?ref="myAuthenticationManager"></beans:property>??
  35. ????????<!--?注入DAO为了查询相应的用户?-->??
  36. ????????<beans:property?name="usersDao"?ref="usersDao"></beans:property>??
  37. ????</beans:bean>??
  38. ????<beans:bean?id="loginLogAuthenticationSuccessHandler"??
  39. ????????class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">??
  40. ????????<beans:property?name="defaultTargetUrl"?value="/index.jsp"></beans:property>??
  41. ????</beans:bean>??
  42. ????<beans:bean?id="simpleUrlAuthenticationFailureHandler"??
  43. ????????class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">??
  44. ????????<!--?可以配置相应的跳转方式。属性forwardToDestination为true采用forward?false为sendRedirect?-->??
  45. ????????<beans:property?name="defaultFailureUrl"?value="/login.jsp"></beans:property>??
  46. ????</beans:bean>??
  47. ??????
  48. ????<!--?认证过滤器?-->??
  49. ????<beans:bean?id="securityFilter"?class="com.huaxin.security.MySecurityFilter">??
  50. ????????<!--?用户拥有的权限?-->??
  51. ????????<beans:property?name="authenticationManager"?ref="myAuthenticationManager"?/>??
  52. ????????<!--?用户是否拥有所请求资源的权限?-->??
  53. ????????<beans:property?name="accessDecisionManager"?ref="myAccessDecisionManager"?/>??
  54. ????????<!--?资源与权限对应关系?-->??
  55. ????????<beans:property?name="securityMetadataSource"?ref="mySecurityMetadataSource"?/>??
  56. ????</beans:bean>??
  57. ????<!--?实现了UserDetailsService的Bean?-->??
  58. ????<authentication-manager?alias="myAuthenticationManager">??
  59. ????????<authentication-provider?user-service-ref="myUserDetailServiceImpl"?/>??
  60. ????</authentication-manager>??
  61. ??????
  62. ????<beans:bean?id="myAccessDecisionManager"?class="com.huaxin.security.MyAccessDecisionManager"></beans:bean>??
  63. ????<beans:bean?id="mySecurityMetadataSource"?class="com.huaxin.security.MySecurityMetadataSource">??
  64. ????????<beans:constructor-arg?name="resourcesDao"?ref="resourcesDao"></beans:constructor-arg>??
  65. ????</beans:bean>??
  66. ????<beans:bean?id="myUserDetailServiceImpl"?class="com.huaxin.security.MyUserDetailServiceImpl">??
  67. ????????<beans:property?name="usersDao"?ref="usersDao"></beans:property>??
  68. ????</beans:bean>??
  69. ??????
  70. ????<!--?未登录的切入点?-->??
  71. ????<beans:bean?id="authenticationProcessingFilterEntryPoint"?class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">??
  72. ????????<beans:property?name="loginFormUrl"?value="/login.jsp"></beans:property>??
  73. ????</beans:bean>??
  74. </beans:beans>??

?

这里特别要说明一下,我们的<http>标签不能配置auto-config,因为这样配置后,依然会采用Spring Security的Filter Chain会与下面我们配的custom-filter冲突,最好会抛异常。还有配置一个切入点entry-point-ref="authenticationProcessingFilterEntryPoint",为了在未登陆的时候,跳转到哪个页面,不配也会抛异常。

?<custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER"? /> position表示替换掉Spring Security原来默认的登陆验证Filter。

?

四、MyUsernamePasswordAuthenticationFilter

?

[java]?view plaincopy
  1. package?com.huaxin.security;??
  2. ??
  3. import?javax.servlet.http.HttpServletRequest;??
  4. import?javax.servlet.http.HttpServletResponse;??
  5. import?javax.servlet.http.HttpSession;??
  6. ??
  7. import?org.apache.commons.lang.xwork.StringUtils;??
  8. import?org.springframework.security.authentication.AuthenticationServiceException;??
  9. import?org.springframework.security.authentication.UsernamePasswordAuthenticationToken;??
  10. import?org.springframework.security.core.Authentication;??
  11. import?org.springframework.security.core.AuthenticationException;??
  12. import?org.springframework.security.web.WebAttributes;??
  13. import?org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;??
  14. ??
  15. import?com.huaxin.bean.Users;??
  16. import?com.huaxin.dao.UsersDao;??
  17. ??
  18. /*?
  19. ?*??
  20. ?*?UsernamePasswordAuthenticationFilter源码?
  21. ????attemptAuthentication?
  22. ????????this.getAuthenticationManager()?
  23. ????????????ProviderManager.java?
  24. ????????????????authenticate(UsernamePasswordAuthenticationToken?authRequest)?
  25. ????????????????????AbstractUserDetailsAuthenticationProvider.java?
  26. ????????????????????????authenticate(Authentication?authentication)?
  27. ????????????????????????????P155?user?=?retrieveUser(username,?(UsernamePasswordAuthenticationToken)?authentication);?
  28. ????????????????????????????????DaoAuthenticationProvider.java?
  29. ????????????????????????????????????P86?loadUserByUsername?
  30. ?*/??
  31. public?class?MyUsernamePasswordAuthenticationFilter?extends?UsernamePasswordAuthenticationFilter{??
  32. ????public?static?final?String?VALIDATE_CODE?=?"validateCode";??
  33. ????public?static?final?String?USERNAME?=?"username";??
  34. ????public?static?final?String?PASSWORD?=?"password";??
  35. ??????
  36. ????private?UsersDao?usersDao;??
  37. ????public?UsersDao?getUsersDao()?{??
  38. ????????return?usersDao;??
  39. ????}??
  40. ????public?void?setUsersDao(UsersDao?usersDao)?{??
  41. ????????this.usersDao?=?usersDao;??
  42. ????}??
  43. ??
  44. ????@Override??
  45. ????public?Authentication?attemptAuthentication(HttpServletRequest?request,?HttpServletResponse?response)?throws?AuthenticationException?{??
  46. ????????if?(!request.getMethod().equals("POST"))?{??
  47. ????????????throw?new?AuthenticationServiceException("Authentication?method?not?supported:?"?+?request.getMethod());??
  48. ????????}??
  49. ????????//检测验证码??
  50. ????????checkValidateCode(request);??
  51. ??????????
  52. ????????String?username?=?obtainUsername(request);??
  53. ????????String?password?=?obtainPassword(request);??
  54. ??????????
  55. ????????//验证用户账号与密码是否对应??
  56. ????????username?=?username.trim();??
  57. ??????????
  58. ????????Users?users?=?this.usersDao.findByName(username);??
  59. ??????????
  60. ????????if(users?==?null?||?!users.getPassword().equals(password))?{??
  61. ????/*?
  62. ??????????????在我们配置的simpleUrlAuthenticationFailureHandler处理登录失败的处理类在这么一段?
  63. ????????这样我们可以在登录失败后,向用户提供相应的信息。?
  64. ????????if?(forwardToDestination)?{?
  65. ????????????request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION,?exception);?
  66. ????????}?else?{?
  67. ????????????HttpSession?session?=?request.getSession(false);?
  68. ?
  69. ????????????if?(session?!=?null?||?allowSessionCreation)?{?
  70. ????????????????request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION,?exception);?
  71. ????????????}?
  72. ????????}?
  73. ?????*/??
  74. ????????????throw?new?AuthenticationServiceException("用户名或者密码错误!");???
  75. ????????}??
  76. ??????????
  77. ????????//UsernamePasswordAuthenticationToken实现?Authentication??
  78. ????????UsernamePasswordAuthenticationToken?authRequest?=?new?UsernamePasswordAuthenticationToken(username,?password);??
  79. ????????//?Place?the?last?username?attempted?into?HttpSession?for?views??
  80. ??????????
  81. ????????//?允许子类设置详细属性??
  82. ????????setDetails(request,?authRequest);??
  83. ??????????
  84. ????????//?运行UserDetailsService的loadUserByUsername?再次封装Authentication??
  85. ????????return?this.getAuthenticationManager().authenticate(authRequest);??
  86. ????}??
  87. ??????
  88. ????protected?void?checkValidateCode(HttpServletRequest?request)?{???
  89. ????????HttpSession?session?=?request.getSession();??
  90. ??????????
  91. ????????String?sessionValidateCode?=?obtainSessionValidateCode(session);???
  92. ????????//让上一次的验证码失效??
  93. ????????session.setAttribute(VALIDATE_CODE,?null);??
  94. ????????String?validateCodeParameter?=?obtainValidateCodeParameter(request);????
  95. ????????if?(StringUtils.isEmpty(validateCodeParameter)?||?!sessionValidateCode.equalsIgnoreCase(validateCodeParameter))?{????
  96. ????????????throw?new?AuthenticationServiceException("验证码错误!");????
  97. ????????}????
  98. ????}??
  99. ??????
  100. ????private?String?obtainValidateCodeParameter(HttpServletRequest?request)?{??
  101. ????????Object?obj?=?request.getParameter(VALIDATE_CODE);??
  102. ????????return?null?==?obj???""?:?obj.toString();??
  103. ????}??
  104. ??
  105. ????protected?String?obtainSessionValidateCode(HttpSession?session)?{??
  106. ????????Object?obj?=?session.getAttribute(VALIDATE_CODE);??
  107. ????????return?null?==?obj???""?:?obj.toString();??
  108. ????}??
  109. ??
  110. ????@Override??
  111. ????protected?String?obtainUsername(HttpServletRequest?request)?{??
  112. ????????Object?obj?=?request.getParameter(USERNAME);??
  113. ????????return?null?==?obj???""?:?obj.toString();??
  114. ????}??
  115. ??
  116. ????@Override??
  117. ????protected?String?obtainPassword(HttpServletRequest?request)?{??
  118. ????????Object?obj?=?request.getParameter(PASSWORD);??
  119. ????????return?null?==?obj???""?:?obj.toString();??
  120. ????}??
  121. ??????
  122. ??????
  123. }??

?

有时间,大家看看源码吧。

?

五、login.jsp

?

[php]?view plaincopy
  1. <body>??
  2. ??<span?style="color:red"><%=session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION)?%></span>??
  3. ???<form?action="j_spring_security_check"?method="post">??
  4. ????Account:<Input?name="username"/><br/>??
  5. ????Password:<input?name="password"?type="password"/><br/>??
  6. ????<input?value="submit"?type="submit"/>??
  7. ???</form>??
  8. ?</body>??

?

?

六、完了,源码大家可以看下我上一篇文章http://blog.csdn.net/k10509806/archive/2011/04/28/6369131.aspx。

读书人网 >软件架构设计

热点推荐