spring security实现传参
来源:互联网 发布:网络的利与弊作文1000 编辑:程序博客网 时间:2024/05/21 11:08
本人现在开发的项目中用到了spring security3.1.2来实现登陆验证,但默认的过滤器UsernamePasswordAuthenticationFilter只能传递两个参数j_username和j_password,如果要传递验证码或首次打开的页面URL参数,只能重写UsernamePasswordAuthenticationFilter。
对于不了解spring security3.1的童鞋,请先阅读本人写的另一篇博客Spring Security权限管理,下面将在这篇博客的基础上,添加一个功能:传递登陆之前的页面URL。公司现在做的项目,如果没有登陆或会话超时,都要求重新登陆,登陆之后会直接跳转到首页,而不是跳转到原来打开的页面,这很恶心。于是本人决心对项目进行改造,使得可以传递最后打开页面的URL,登陆之后直接跳转到这个URL去。
1.重写UsernamePasswordAuthenticationFilter
package com.web.filter;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;import org.springframework.security.core.Authentication;import org.springframework.security.core.AuthenticationException;import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;import org.springframework.util.Assert;/** * 验证登陆用户名和密码的拦截器,记录最后登陆页面 * @author brushli * @date 2014-10-30 */public class MyUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter { public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username"; public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password"; public static final String SPRING_SECURITY_FORM_LAST_LOGIN_URL_KEY = "lastLoginUrl"; public static final String SPRING_SECURITY_SPLIT = ","; /** * @deprecated If you want to retain the username, cache it in a customized {@code AuthenticationFailureHandler} */ @Deprecated public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME"; private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY; private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY; private String lastLoginUrlParameter = SPRING_SECURITY_FORM_LAST_LOGIN_URL_KEY; private String split = SPRING_SECURITY_SPLIT; private boolean postOnly = true; //~ Constructors =================================================================================================== public MyUsernamePasswordAuthenticationFilter() { super("/j_spring_security_check"); } //~ Methods ======================================================================================================== public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException { if (postOnly && !request.getMethod().equals("POST")) {// throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod()); } String username = obtainUsername(request); String password = obtainPassword(request); String lastLoginUrl = obtainLastLoginUrl(request); if (username == null) { username = ""; } if (password == null) { password = ""; } if (lastLoginUrl == null) { lastLoginUrl = ""; } username = username.trim(); username = username + SPRING_SECURITY_SPLIT + lastLoginUrl; UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); // Allow subclasses to set the "details" property setDetails(request, authRequest); return this.getAuthenticationManager().authenticate(authRequest); } /** * Enables subclasses to override the composition of the password, such as by including additional values * and a separator.<p>This might be used for example if a postcode/zipcode was required in addition to the * password. A delimiter such as a pipe (|) should be used to separate the password and extended value(s). The * <code>AuthenticationDao</code> will need to generate the expected password in a corresponding manner.</p> * * @param request so that request attributes can be retrieved * * @return the password that will be presented in the <code>Authentication</code> request token to the * <code>AuthenticationManager</code> */ protected String obtainPassword(HttpServletRequest request) { return request.getParameter(passwordParameter); } /** * Enables subclasses to override the composition of the username, such as by including additional values * and a separator. * * @param request so that request attributes can be retrieved * * @return the username that will be presented in the <code>Authentication</code> request token to the * <code>AuthenticationManager</code> */ protected String obtainUsername(HttpServletRequest request) { return request.getParameter(usernameParameter); } protected String obtainLastLoginUrl(HttpServletRequest request) { return request.getParameter(lastLoginUrlParameter); } /** * Provided so that subclasses may configure what is put into the authentication request's details * property. * * @param request that an authentication request is being created for * @param authRequest the authentication request object that should have its details set */ protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) { authRequest.setDetails(authenticationDetailsSource.buildDetails(request)); } /** * Sets the parameter name which will be used to obtain the username from the login request. * * @param usernameParameter the parameter name. Defaults to "j_username". */ public void setUsernameParameter(String usernameParameter) { Assert.hasText(usernameParameter, "Username parameter must not be empty or null"); this.usernameParameter = usernameParameter; } /** * Sets the parameter name which will be used to obtain the password from the login request.. * * @param passwordParameter the parameter name. Defaults to "j_password". */ public void setPasswordParameter(String passwordParameter) { Assert.hasText(passwordParameter, "Password parameter must not be empty or null"); this.passwordParameter = passwordParameter; } /** * Defines whether only HTTP POST requests will be allowed by this filter. * If set to true, and an authentication request is received which is not a POST request, an exception will * be raised immediately and authentication will not be attempted. The <tt>unsuccessfulAuthentication()</tt> method * will be called as if handling a failed authentication. * <p> * Defaults to <tt>true</tt> but may be overridden by subclasses. */ public void setPostOnly(boolean postOnly) { this.postOnly = postOnly; } public final String getUsernameParameter() { return usernameParameter; } public final String getPasswordParameter() { return passwordParameter; }public String getLastLoginUrlParameter() {return lastLoginUrlParameter;}public void setLastLoginUrlParameter(String lastLoginUrlParameter) {Assert.hasText(lastLoginUrlParameter, "lastLoginUrl Parameter must not be empty or null");this.lastLoginUrlParameter = lastLoginUrlParameter;}public String getSplit() {return split;}/** * The string to separate username and lastLoginUrl * @param split */public void setSplit(String split) {this.split = split;}}
2.修改AuthenticationFailHandlerImpl
package com.service.impl; import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.security.core.AuthenticationException;import org.springframework.security.web.authentication.AuthenticationFailureHandler;import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;public class AuthenticationFailHandlerImpl extends SimpleUrlAuthenticationFailureHandler implements AuthenticationFailureHandler {/** * 登录时密码或账号不正确时的操作 */@Overridepublic void onAuthenticationFailure(HttpServletRequest request,HttpServletResponse response, AuthenticationException exception)throws IOException, ServletException {String lastLoginUrl = request.getParameter("lastLoginUrl");if(lastLoginUrl == null){lastLoginUrl = "";}lastLoginUrl = lastLoginUrl.replace("?", "%3F");lastLoginUrl = lastLoginUrl.replace("&", "%26");logger.info("lastLoginUrl=" + lastLoginUrl);response.sendRedirect(request.getContextPath() + "/login.jsp?result=0&lastLoginUrl="+lastLoginUrl);return;}}
3.修改AuthenticationSuccessHandlerImpl
package com.service.impl;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import org.springframework.security.core.Authentication;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.security.web.authentication.AuthenticationSuccessHandler;import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;import com.bean.UserLoginDetails;/** * Authentication Handler for redirect the original inputed URL after login system. */public class AuthenticationSuccessHandlerImpl extends SimpleUrlAuthenticationSuccessHandler implements AuthenticationSuccessHandler {/** * 登录时通过密码验证后进行的操作 */@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {//查询当前登录用户有权限的功能if(!SecurityContextHolder.getContext().getAuthentication().getPrincipal().equals("anonymousUser")){UserLoginDetails userDetails = (UserLoginDetails) authentication.getPrincipal();HttpSession session = request.getSession();session.setAttribute("userDetails", userDetails);logger.info("lastLoginUrl=" + userDetails.getLastLoginUrl());if(userDetails.getLastLoginUrl() != null && !"".equals(userDetails.getLastLoginUrl().trim())){response.sendRedirect(userDetails.getLastLoginUrl());}else{response.sendRedirect(request.getContextPath() + "/myPage/myPage.jsp");}}return;}}
4.修改WebUserDetailsService
package com.service.impl;import java.util.HashSet;import java.util.Set;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.SimpleGrantedAuthority;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.core.userdetails.UsernameNotFoundException;import com.bean.Role;import com.bean.User;import com.bean.UserLoginDetails;import com.service.UserService;import com.web.filter.MyUsernamePasswordAuthenticationFilter;/** * 用户登录是准备阶段的业务逻辑 */public class WebUserDetailsService implements UserDetailsService {protected static final Logger logger = LoggerFactory.getLogger(WebUserDetailsService.class);private UserService userService;public void setUserService(UserService userService) {this.userService = userService;}@Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {boolean accountNonExpired = true; boolean credentialsNonExpired = true; boolean accountNonLocked = true; boolean enabled = true; String[] usernameLastLoginUrl = username.split(MyUsernamePasswordAuthenticationFilter.SPRING_SECURITY_SPLIT);String lastLoginUrl = "";if(usernameLastLoginUrl.length == 1){username = usernameLastLoginUrl[0];}else if(usernameLastLoginUrl.length == 2){username = usernameLastLoginUrl[0];lastLoginUrl = usernameLastLoginUrl[1];} User user = null; try {user = userService.getUserByUsername(username);} catch (Exception e) {e.printStackTrace();} if(user == null){throw new UsernameNotFoundException("User account : " + username + " not found!");} //封装该用户具有什么角色 Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>(); if(user.getRoles() != null && !user.getRoles().isEmpty()){ for(Role role : user.getRoles()){ GrantedAuthority ga = new SimpleGrantedAuthority(role.getName()); authorities.add(ga); } } UserLoginDetails userLoginDetails = new UserLoginDetails(user.getUsername(), user.getPassword(), authorities, accountNonExpired, accountNonLocked, credentialsNonExpired, enabled, lastLoginUrl); return userLoginDetails;}}
5.修改UserLoginDetails
package com.bean;import java.util.Collection;import java.util.Set;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.userdetails.UserDetails;public class UserLoginDetails implements UserDetails {private static final long serialVersionUID = 1L;private String username;private String password;private Set<GrantedAuthority> authorities = null;private boolean accountNonExpired = false;//账号未过期 private boolean accountNonLocked = false;//账号未锁定 private boolean credentialsNonExpired = false;//证书未过期 private boolean enabled = false;//是否可用 private final String lastLoginUrl;//最后登陆的页面 public UserLoginDetails(String username, String password, Set<GrantedAuthority> authorities, boolean accountNonExpired, boolean accountNonLocked, boolean credentialsNonExpired, boolean enabled, String lastLoginUrl){ this.username = username; this.password = password; this.authorities = authorities; this.accountNonExpired = accountNonExpired; this.accountNonLocked = accountNonLocked; this.credentialsNonExpired = credentialsNonExpired; this.enabled = enabled; this.lastLoginUrl = lastLoginUrl; } public Collection<? extends GrantedAuthority> getAuthorities() {return authorities;}public String getPassword() {return password;}public String getUsername() {return username;}public boolean isAccountNonExpired() {return accountNonExpired;}public boolean isAccountNonLocked() {return accountNonLocked;}public boolean isCredentialsNonExpired() {return credentialsNonExpired;}public boolean isEnabled() {return enabled;}public String getLastLoginUrl() {return lastLoginUrl;}}
6.修改配置文件
<?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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"><!-- 访问login.jsp页面不需要权限验证 --><http pattern="/login.jsp" security="none"/><!-- This is where we configure Spring-Security --><!-- <http auto-config="true" use-expressions="true"> --><http auto-config="false" use-expressions="true" access-denied-page="/deny.jsp" entry-point-ref="authenticationEntryPoint"><intercept-url pattern="/admin/**" access="hasRole('admin')"/><!-- 用户只有拥有角色admin才能访问/admin目录下面的资源 --><intercept-url pattern="/myPage/**"access="hasAnyRole('admin', 'myRole')"/><!-- 用户拥有角色admin,myRole中的任意一个就能访问/myPage目录下面的资源 --><!-- <form-loginlogin-page="/login.jsp"authentication-failure-url="/deny.jsp" default-target-url="/index.jsp" authentication-success-handler-ref="authenticationSuccessHandlerImpl"authentication-failure-handler-ref="authenticationFailHandlerImpl"/> --><!-- 配置自定义的Filter,并且将其放在FORM_LOGIN_FILTER节点,就会替换掉原来的FORM_LOGIN_FILTER节点 设置auto-config="false",不然会报已经存在同样的过滤器错误,同时还要删除<form-login> --><custom-filter ref="loginProcessFilter" position ="FORM_LOGIN_FILTER" /><logout invalidate-session="true" logout-success-url="/login.jsp" /> <!-- 增加一个自定义的filter,放在FILTER_SECURITY_INTERCEPTOR之前, 实现用户、角色、权限、资源的数据库管理。 --> <custom-filter ref="securityFilter" before="FILTER_SECURITY_INTERCEPTOR"/> </http><beans:bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint"> <beans:property name="loginFormUrl" value="/login.jsp"></beans:property> </beans:bean><beans:bean id="loginProcessFilter" class="com.web.filter.MyUsernamePasswordAuthenticationFilter"><beans:property name="authenticationManager" ref="authenticationManagerService"></beans:property><beans:property name="authenticationSuccessHandler" ref="authenticationSuccessHandlerImpl"></beans:property><beans:property name="authenticationFailureHandler" ref="authenticationFailHandlerImpl"></beans:property></beans:bean><beans:bean id="securityFilter" class="com.filter.SecurityInterceptorFilter"> <beans:property name="authenticationManager" ref="authenticationManagerService"/> <beans:property name="accessDecisionManager" ref="accessDecisionManagerService"/> <beans:property name="securityMetadataSource" ref="securityMetadataSourceService"/> </beans:bean><beans:bean id="securityMetadataSourceService" class="com.service.impl.SecurityMetadataSourceService" init-method="loadAllResources"> <beans:property name="userService" ref="userService"/></beans:bean><!-- Declare an authentication-manager to use a custom userDetailsService --><authentication-manager alias="authenticationManagerService"><authentication-provider user-service-ref="webUserDetailsService"> <password-encoder hash="md5" /></authentication-provider></authentication-manager><beans:bean id="accessDecisionManagerService" class="com.service.impl.AccessDecisionManagerService" /> </beans:beans>
7.程序运行结果
我们打开首页:http://localhost:8082/springSecurity/index.jsp
程序会自动跳转到登陆页面:http://localhost:8082/springSecurity/login.jsp?lastLoginUrl=/springSecurity/index.jsp
后面会附带首页的URL,输入正确的用户名和密码后,就会自动跳转到首页
7.项目的代码结构
8.项目源代码下载
包括整个项目的源代码和MYSQL建库脚本
http://download.csdn.net/detail/brushli/7865697
- spring security实现传参
- Spring Security 实现身份认证
- Spring Security实现权限管理
- Spring security实现权限管理
- spring security oauth2.0 实现
- spring-security实现权限管理
- Spring security实现权限管理
- spring security oauth2.0 实现
- Spring security实现权限管理
- Spring security实现权限管理
- Spring security实现权限管理
- Spring security实现权限管理
- Spring security实现权限管理
- Spring security实现权限管理
- spring security oauth2.0 实现
- Spring Security教程之Spring Security实现访问控制
- 关于struts2和spring security的结合以及spring security传参的问题
- Spring Security调研记录【三】--实现Method Security
- ArcGIS教程:创建“隐形”图层
- sqlServer 2008 重建sa
- linux关于tomcat的一些命令笔记
- 利用TF-IDF 提取文章关键词
- IOS中的结构体保存到数组与读取
- spring security实现传参
- Shell脚本通过参数传递调用指定函数
- libnml 通信
- 超越Objective-C,超越Swift
- HttpClient使用详解
- Android - TabHost 选项卡功能用法布局详细讲解(1)
- Power平台安装Redhat/SUSE Linux时引导报错解决方案
- xamarin.ios 绑定 oc libray
- 关于android手机充电时间的计算公式