Spring Security3.1登陆验证

Stella981
• 阅读 426

一、前言

在上一篇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 plain copy

  1. <beans:beans xmlns="http://www.springframework.org/schema/security"

  2. xmlns:beans="http://www.springframework.org/schema/beans"

  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  4. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd

  5. http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"\>

  6. <http pattern="/js/**" security="none"/>

  7. <http pattern="/resource/**" security="none"></http>

  8. <http pattern="/login.jsp" security="none"/>

  9. <http use-expressions="true" entry-point-ref="authenticationProcessingFilterEntryPoint">

  10. <session-management invalid-session-url="/timeout.jsp">

  11. <concurrency-control max-sessions="10" error-if-maximum-exceeded="true" />

  12. </session-management>

  13. <custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER" />

  14. <custom-filter ref="securityFilter" before="FILTER_SECURITY_INTERCEPTOR"/>

  15. </http>

  16. <beans:bean id="loginFilter"

  17. class="com.huaxin.security.MyUsernamePasswordAuthenticationFilter">

  18. <beans:property name="filterProcessesUrl" value="/j_spring_security_check"></beans:property>

  19. <beans:property name="authenticationSuccessHandler" ref="loginLogAuthenticationSuccessHandler"></beans:property>

  20. <beans:property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler"></beans:property>

  21. <beans:property name="authenticationManager" ref="myAuthenticationManager"></beans:property>

  22. <beans:property name="usersDao" ref="usersDao"></beans:property>

  23. </beans:bean>

  24. <beans:bean id="loginLogAuthenticationSuccessHandler"

  25. class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">

  26. <beans:property name="defaultTargetUrl" value="/index.jsp"></beans:property>

  27. </beans:bean>

  28. <beans:bean id="simpleUrlAuthenticationFailureHandler"

  29. class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">

  30. <beans:property name="defaultFailureUrl" value="/login.jsp"></beans:property>

  31. </beans:bean>

  32. <beans:bean id="securityFilter" class="com.huaxin.security.MySecurityFilter">

  33. <beans:property name="authenticationManager" ref="myAuthenticationManager" />

  34. <beans:property name="accessDecisionManager" ref="myAccessDecisionManager" />

  35. <beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" />

  36. </beans:bean>

  37. <authentication-manager alias="myAuthenticationManager">

  38. <authentication-provider user-service-ref="myUserDetailServiceImpl" />

  39. </authentication-manager>

  40. <beans:bean id="myAccessDecisionManager" class="com.huaxin.security.MyAccessDecisionManager"></beans:bean>

  41. <beans:bean id="mySecurityMetadataSource" class="com.huaxin.security.MySecurityMetadataSource">

  42. <beans:constructor-arg name="resourcesDao" ref="resourcesDao"></beans:constructor-arg>

  43. </beans:bean>

  44. <beans:bean id="myUserDetailServiceImpl" class="com.huaxin.security.MyUserDetailServiceImpl">

  45. <beans:property name="usersDao" ref="usersDao"></beans:property>

  46. </beans:bean>

  47. <beans:bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">

  48. <beans:property name="loginFormUrl" value="/login.jsp"></beans:property>

  49. </beans:bean>

  50. </beans:beans>

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

position表示替换掉Spring Security原来默认的登陆验证Filter。

四、MyUsernamePasswordAuthenticationFilter

[java] view plain copy

  1. package com.huaxin.security;

  2. import javax.servlet.http.HttpServletRequest;

  3. import javax.servlet.http.HttpServletResponse;

  4. import javax.servlet.http.HttpSession;

  5. import org.apache.commons.lang.xwork.StringUtils;

  6. import org.springframework.security.authentication.AuthenticationServiceException;

  7. import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;

  8. import org.springframework.security.core.Authentication;

  9. import org.springframework.security.core.AuthenticationException;

  10. import org.springframework.security.web.WebAttributes;

  11. import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

  12. import com.huaxin.bean.Users;

  13. import com.huaxin.dao.UsersDao;

  14. /*

  15. *

  16. * UsernamePasswordAuthenticationFilter源码

  17. attemptAuthentication

  18. this.getAuthenticationManager()

  19. ProviderManager.java

  20. authenticate(UsernamePasswordAuthenticationToken authRequest)

  21. AbstractUserDetailsAuthenticationProvider.java

  22. authenticate(Authentication authentication)

  23. P155 user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);

  24. DaoAuthenticationProvider.java

  25. P86 loadUserByUsername

  26. */

  27. public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{

  28. public static final String VALIDATE_CODE = "validateCode";

  29. public static final String USERNAME = "username";

  30. public static final String PASSWORD = "password";

  31. private UsersDao usersDao;

  32. public UsersDao getUsersDao() {

  33. return usersDao;

  34. }

  35. public void setUsersDao(UsersDao usersDao) {

  36. this.usersDao = usersDao;

  37. }

  38. @Override

  39. public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

  40. if (!request.getMethod().equals("POST")) {

  41. throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());

  42. }

  43. //检测验证码

  44. checkValidateCode(request);

  45. String username = obtainUsername(request);

  46. String password = obtainPassword(request);

  47. //验证用户账号与密码是否对应

  48. username = username.trim();

  49. Users users = this.usersDao.findByName(username);

  50. if(users == null || !users.getPassword().equals(password)) {

  51. /*

  52. 在我们配置的simpleUrlAuthenticationFailureHandler处理登录失败的处理类在这么一段

  53. 这样我们可以在登录失败后,向用户提供相应的信息。

  54. if (forwardToDestination) {

  55. request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);

  56. } else {

  57. HttpSession session = request.getSession(false);

  58. if (session != null || allowSessionCreation) {

  59. request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception);

  60. }

  61. }

  62. */

  63. throw new AuthenticationServiceException("用户名或者密码错误!");

  64. }

  65. //UsernamePasswordAuthenticationToken实现 Authentication

  66. UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);

  67. // Place the last username attempted into HttpSession for views

  68. // 允许子类设置详细属性

  69. setDetails(request, authRequest);

  70. // 运行UserDetailsService的loadUserByUsername 再次封装Authentication

  71. return this.getAuthenticationManager().authenticate(authRequest);

  72. }

  73. protected void checkValidateCode(HttpServletRequest request) {

  74. HttpSession session = request.getSession();

  75. String sessionValidateCode = obtainSessionValidateCode(session);

  76. //让上一次的验证码失效

  77. session.setAttribute(VALIDATE_CODE, null);

  78. String validateCodeParameter = obtainValidateCodeParameter(request);

  79. if (StringUtils.isEmpty(validateCodeParameter) || !sessionValidateCode.equalsIgnoreCase(validateCodeParameter)) {

  80. throw new AuthenticationServiceException("验证码错误!");

  81. }

  82. }

  83. private String obtainValidateCodeParameter(HttpServletRequest request) {

  84. Object obj = request.getParameter(VALIDATE_CODE);

  85. return null == obj ? "" : obj.toString();

  86. }

  87. protected String obtainSessionValidateCode(HttpSession session) {

  88. Object obj = session.getAttribute(VALIDATE_CODE);

  89. return null == obj ? "" : obj.toString();

  90. }

  91. @Override

  92. protected String obtainUsername(HttpServletRequest request) {

  93. Object obj = request.getParameter(USERNAME);

  94. return null == obj ? "" : obj.toString();

  95. }

  96. @Override

  97. protected String obtainPassword(HttpServletRequest request) {

  98. Object obj = request.getParameter(PASSWORD);

  99. return null == obj ? "" : obj.toString();

  100. }

  101. }

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

五、login.jsp

[php] view plain copy

  1. <span style="color:red"><%=session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION) %>
  2. <form action="j_spring_security_check" method="post">
  3. Account:
  4. Password:

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

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
java将前端的json数组字符串转换为列表
记录下在前端通过ajax提交了一个json数组的字符串,在后端如何转换为列表。前端数据转化与请求varcontracts{id:'1',name:'yanggb合同1'},{id:'2',name:'yanggb合同2'},{id:'3',name:'yang
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
P2P技术揭秘.P2P网络技术原理与典型系统开发
Modular.Java(2009.06)\.Craig.Walls.文字版.pdf:http://www.t00y.com/file/59501950(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fwww.t00y.com%2Ffile%2F59501950)\More.E
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这