Spring Security3.1登陆验证(转)
来源:互联网 发布:mama投票软件 编辑:程序博客网 时间:2024/06/11 08:03
声明:本文是转载的,用来学习用,还望原著见谅原著地址
一、前言
在上一篇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配置
<?xml version="1.0" encoding="UTF-8"?> <beans:beans xmlns="http://www.springframework.org/schema/security" xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd"> <debug/> <http pattern="/js/**" security="none"/> <http pattern="/resource/**" security="none"></http> <http pattern="/login.jsp" security="none"/> <http use-expressions="true" entry-point-ref="authenticationProcessingFilterEntryPoint"> <logout/> <!-- 实现免登陆验证 --> <remember-me /> <session-management invalid-session-url="/timeout.jsp"> <concurrency-control max-sessions="10" error-if-maximum-exceeded="true" /> </session-management> <custom-filter ref="loginFilter" position="FORM_LOGIN_FILTER" /> <custom-filter ref="securityFilter" before="FILTER_SECURITY_INTERCEPTOR"/> </http> <!-- 登录验证器 --> <beans:bean id="loginFilter" class="com.huaxin.security.MyUsernamePasswordAuthenticationFilter"> <!-- 处理登录的action --> <beans:property name="filterProcessesUrl" value="/j_spring_security_check"></beans:property> <!-- 验证成功后的处理--> <beans:property name="authenticationSuccessHandler" ref="loginLogAuthenticationSuccessHandler"></beans:property> <!-- 验证失败后的处理--> <beans:property name="authenticationFailureHandler" ref="simpleUrlAuthenticationFailureHandler"></beans:property> <beans:property name="authenticationManager" ref="myAuthenticationManager"></beans:property> <!-- 注入DAO为了查询相应的用户 --> <beans:property name="usersDao" ref="usersDao"></beans:property> </beans:bean> <beans:bean id="loginLogAuthenticationSuccessHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler"> <beans:property name="defaultTargetUrl" value="/index.jsp"></beans:property> </beans:bean> <beans:bean id="simpleUrlAuthenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler"> <!-- 可以配置相应的跳转方式。属性forwardToDestination为true采用forward false为sendRedirect --> <beans:property name="defaultFailureUrl" value="/login.jsp"></beans:property> </beans:bean> <!-- 认证过滤器 --> <beans:bean id="securityFilter" class="com.huaxin.security.MySecurityFilter"> <!-- 用户拥有的权限 --> <beans:property name="authenticationManager" ref="myAuthenticationManager" /> <!-- 用户是否拥有所请求资源的权限 --> <beans:property name="accessDecisionManager" ref="myAccessDecisionManager" /> <!-- 资源与权限对应关系 --> <beans:property name="securityMetadataSource" ref="mySecurityMetadataSource" /> </beans:bean> <!-- 实现了UserDetailsService的Bean --> <authentication-manager alias="myAuthenticationManager"> <authentication-provider user-service-ref="myUserDetailServiceImpl" /> </authentication-manager> <beans:bean id="myAccessDecisionManager" class="com.huaxin.security.MyAccessDecisionManager"></beans:bean> <beans:bean id="mySecurityMetadataSource" class="com.huaxin.security.MySecurityMetadataSource"> <beans:constructor-arg name="resourcesDao" ref="resourcesDao"></beans:constructor-arg> </beans:bean> <beans:bean id="myUserDetailServiceImpl" class="com.huaxin.security.MyUserDetailServiceImpl"> <beans:property name="usersDao" ref="usersDao"></beans:property> </beans:bean> <!-- 未登录的切入点 --> <beans:bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"> <beans:property name="loginFormUrl" value="/login.jsp"></beans:property> </beans:bean> </beans:beans>
这里特别要说明一下,我们的标签不能配置auto-config,因为这样配置后,依然会采用Spring Security的Filter Chain会与下面我们配的custom-filter冲突,最好会抛异常。还有配置一个切入点entry-point-ref=”authenticationProcessingFilterEntryPoint”,为了在未登陆的时候,跳转到哪个页面,不配也会抛异常。
position表示替换掉Spring Security原来默认的登陆验证Filter。
四、MyUsernamePasswordAuthenticationFilter
package com.huaxin.security; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.apache.commons.lang.xwork.StringUtils; import org.springframework.security.authentication.AuthenticationServiceException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.WebAttributes; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import com.huaxin.bean.Users; import com.huaxin.dao.UsersDao; /* * * UsernamePasswordAuthenticationFilter源码 attemptAuthentication this.getAuthenticationManager() ProviderManager.java authenticate(UsernamePasswordAuthenticationToken authRequest) AbstractUserDetailsAuthenticationProvider.java authenticate(Authentication authentication) P155 user = retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication); DaoAuthenticationProvider.java P86 loadUserByUsername */ public class MyUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{ public static final String VALIDATE_CODE = "validateCode"; public static final String USERNAME = "username"; public static final String PASSWORD = "password"; private UsersDao usersDao; public UsersDao getUsersDao() { return usersDao; } public void setUsersDao(UsersDao usersDao) { this.usersDao = usersDao; } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { if (!request.getMethod().equals("POST")) { throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod()); } //检测验证码 checkValidateCode(request); String username = obtainUsername(request); String password = obtainPassword(request); //验证用户账号与密码是否对应 username = username.trim(); Users users = this.usersDao.findByName(username); if(users == null || !users.getPassword().equals(password)) { /* 在我们配置的simpleUrlAuthenticationFailureHandler处理登录失败的处理类在这么一段 这样我们可以在登录失败后,向用户提供相应的信息。 if (forwardToDestination) { request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception); } else { HttpSession session = request.getSession(false); if (session != null || allowSessionCreation) { request.getSession().setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception); } } */ throw new AuthenticationServiceException("用户名或者密码错误!"); } //UsernamePasswordAuthenticationToken实现 Authentication UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); // Place the last username attempted into HttpSession for views // 允许子类设置详细属性 setDetails(request, authRequest); // 运行UserDetailsService的loadUserByUsername 再次封装Authentication return this.getAuthenticationManager().authenticate(authRequest); } protected void checkValidateCode(HttpServletRequest request) { HttpSession session = request.getSession(); String sessionValidateCode = obtainSessionValidateCode(session); //让上一次的验证码失效 session.setAttribute(VALIDATE_CODE, null); String validateCodeParameter = obtainValidateCodeParameter(request); if (StringUtils.isEmpty(validateCodeParameter) || !sessionValidateCode.equalsIgnoreCase(validateCodeParameter)) { throw new AuthenticationServiceException("验证码错误!"); } } private String obtainValidateCodeParameter(HttpServletRequest request) { Object obj = request.getParameter(VALIDATE_CODE); return null == obj ? "" : obj.toString(); } protected String obtainSessionValidateCode(HttpSession session) { Object obj = session.getAttribute(VALIDATE_CODE); return null == obj ? "" : obj.toString(); } @Override protected String obtainUsername(HttpServletRequest request) { Object obj = request.getParameter(USERNAME); return null == obj ? "" : obj.toString(); } @Override protected String obtainPassword(HttpServletRequest request) { Object obj = request.getParameter(PASSWORD); return null == obj ? "" : obj.toString(); } }
有时间,大家看看源码吧。
五、login.jsp
body> <span style="color:red"><%=session.getAttribute(WebAttributes.AUTHENTICATION_EXCEPTION) %></span> <form action="j_spring_security_check" method="post"> Account:<Input name="username"/><br/> Password:<input name="password" type="password"/><br/> <input value="submit" type="submit"/> </form> </body>
六、完了,源码大家可以看下我上一篇文章http://blog.csdn.net/k10509806/archive/2011/04/28/6369131.aspx。
- Spring Security3.1登陆验证(转)
- Spring Security3.1登陆验证
- Spring Security3.1登陆验证
- Spring Security3.1登陆验证
- Spring Security3.1登陆验证
- Spring Security3.1配置实例(转)
- Spring Security3.1
- Spring Security3.1实践
- Spring Security3.1实践
- Spring Security3.1实践
- spring security3(一)登录验证
- spring security3教程系列--扩展验证码
- spring security3 实现验证码配置
- spring security3教程系列--扩展验证码
- Spring security3.x 自定义验证Filter
- Spring Security3.1权限管理
- Spring Security3.1 配置说明
- Spring Security3.1 配置说明
- Hibernate的学习之路十二(session的快照机制)
- 简单四步完成Oracle创建表空间
- Android系统字体大小如何影响app的字体大小?
- 什么是索引?索引有哪几种?什么时候使用索引比较好?
- 基于Spring的QQ第三方登录实现
- Spring Security3.1登陆验证(转)
- Cron表达式
- observeOn()与subscribeOn()的详解
- iOS 11 & iPhoneX 适配
- adb shell下查看sqlite数据库
- 机房收费系统-登录
- python模拟打开Google浏览器并打开网页
- Aja5
- [Leetcode] 484. Find Permutation 解题报告