spring security四种实现方式
来源:互联网 发布:cpu评测软件 编辑:程序博客网 时间:2024/06/05 11:26
spring security实现方式大致可以分为这几种:
1.配置文件实现,只需要在配置文件中指定拦截的url所需要权限、配置userDetailsService指定用户名、密码、对应权限,就可以实现。
2.实现UserDetailsService,loadUserByUsername(String userName)方法,根据userName来实现自己的业务逻辑返回UserDetails的实现类,需要自定义User类实现UserDetails,比较重要的方法是getAuthorities(),用来返回该用户所拥有的权限。
3.通过自定义filter重写spring security拦截器,实现动态过滤用户权限。
4.通过自定义filter重写spring security拦截器,实现自定义参数来检验用户,并且过滤权限。
1.最简单配置spring-security.xml,实现1
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:security="http://www.springframework.org/schema/security" xmlns:p="http://www.springframework.org/schema/p" 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-4.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd"> <!-- use-expressions:Spring 表达式语言配置访问控制 --> <security:http auto-config="true" use-expressions="false"> <!-- 配置权限拦截,访问所有url,都需要用户登录,且拥有ROLE_USER权限 --> <security:intercept-url pattern="/**" access="ROLE_USER" /> </security:http> <security:authentication-manager alias="authenticationManager"> <security:authentication-provider> <!-- 配置默认用户,用户名:admin 密码:123456 拥有权限:ROLE_USER --> <security:user-service> <security:user name="admin" password="123456" authorities="ROLE_USER" /> </security:user-service> </security:authentication-provider> </security:authentication-manager> </beans>
2.实现UserDetailsService
先整理下spring secruity验证流程:
springSecurity的登录验证是由org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter这个过滤器来完成的,在该类的父类AbstractAuthenticationProcessingFilter中有一个AuthenticationManager接口属性,验证工作主要是通过这个AuthenticationManager接口的实例来完成的。在默认情况下,springSecurity框架会把org.springframework.security.authentication.ProviderManager类的实例注入到该属性
UsernamePasswordAuthenticationFilter的验证过程如下:
1. 首先过滤器会调用自身的attemptAuthentication方法,从request中取出authentication, authentication是在org.springframework.security.web.context.SecurityContextPersistenceFilter过滤器中通过捕获用户提交的登录表单中的内容生成的一个org.springframework.security.core.Authentication接口实例.
2. 拿到authentication对象后,过滤器会调用ProviderManager类的authenticate方法,并传入该对象
3.ProviderManager类的authenticate方法中会调用类中的List<AuthenticationProvider> providers集合中的各个AuthenticationProvider接口实现类中的authenticate(Authentication authentication)方法进行验证,由此可见,真正的验证逻辑是由各个AuthenticationProvider接口实现类来完成的。DaoAuthenticationProvider类是默认情况下注入的一个AuthenticationProvider接口实现类
4.provider的实现类在验证用户时,会调用userDetailsService的实现类的loadUserByUsername方法来获取用户信息,
首先spring-security配置文件
<?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-4.3.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> <!-- use-expressions=”true” 需要使用表达式方式来写权限--><http auto-config="true" use-expressions="false"> <!--这是spring 提供的http/https信道安全的这个是重要的!你的请求信道是安全的!--> <!-- 释放用户登陆page 允许任何人访问该页面 ,IS_AUTHENTICATED_ANONYMOUSLY表示不拦截 另一种不拦截资源的配置:<http pattern="/login.jsp" security="none"> --> <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/> <!-- 配置用户正常访问page--> <intercept-url pattern="/**" access="ROLE_USER"/> <!-- 自定义用户登陆page default-target-url登陆成功跳转的page ,authentication-failure-url="/login.jsp?error=true"这里是登陆失败跳转的page--> <form-login login-page="/login.jsp" default-target-url="/jsp/index/main.jsp" authentication-failure-url="/login.jsp?error=true"/> <!-- 记住密码 --><!-- <remember-me key="elim" user-service-ref="securityManager"/> --> </http> <authentication-manager alias="authenticationManager"><!-- authentication-provider 引用UserDetailsService实现类时使用user-service-ref属性,引用authentication实现类时,使用ref属性 这两个属性的区别在于 ref:直接将ref依赖的bean注入到AuthenticationProvider的providers集合中 user-service-ref:定义DaoAuthenticationProvider的bean注入到AuthenticationProvider的providers集合中, 并且DaoAuthenticationProvider的变量userDetailsService由user-service-ref依赖的bean注入。--><authentication-provider user-service-ref="msecurityManager"><!-- 密码加密 --><password-encoder ref="myPasswordEncoder"/></authentication-provider></authentication-manager><!-- 实现UserDetailsService --><beans:bean id="msecurityManager" class="com.ultrapower.me.util.security.support.SecurityManagerSupport"></beans:bean><!-- 密码加密 --><beans:bean id="myPasswordEncoder" class="com.ultrapower.me.util.security.MyPasswordEncoder"/></beans:beans>
userDetailsService实现:
/** * */package com.ultrapower.me.util.security.support;import java.util.ArrayList;import java.util.HashMap;import java.util.HashSet;import java.util.List;import java.util.Map;import java.util.Set;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.springframework.dao.DataAccessException;import org.springframework.jdbc.core.JdbcTemplate;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.core.userdetails.UsernameNotFoundException;import com.ultrapower.me.util.Constants;import com.ultrapower.me.util.dbDao.SpringBeanUtil;import com.ultrapower.me.util.security.SecurityManager;import com.ultrapower.me.util.security.entity.Resource;import com.ultrapower.me.util.security.entity.Role;import com.ultrapower.me.util.security.entity.User;import com.ultrapower.me.util.task.PasswordUtils;public class SecurityManagerSupport implements UserDetailsService{private Log log = LogFactory.getLog(this.getClass().getName()); public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException {// List<User> users = getHibernateTemplate().find("FROM User user WHERE user.name = ? AND user.disabled = false", userName); log.info("SecurityManagerSupport.loadUserByUsername.userName:"+userName); User user =null; if("admin".equals(userName)){ Set<Role> roles = new HashSet<Role>() ; Role role = new Role(); role.setRoleid("ROLE_USER"); role.setRoleName("ROLE_USER"); Set<Resource> resources=new HashSet<Resource>() ; Resource res = new Resource(); res.setResid("ME001"); res.setResName("首页"); res.setResUrl("/jsp/index/main.jsp"); res.setType("ROLE_USER"); res.setRoles(roles); resources.add(res); role.setResources(resources); roles.add(role); user = new User(); user.setAccount("admin"); user.setDisabled(false); user.setPassword(PasswordUtils.entryptPassword(Constants.securityKey)); log.info(user.getPassword()); user.setRoles(roles); } return user;//返回UserDetails的实现user不为空,则验证通过 } }
UserDetails实现:
/** * */package com.ultrapower.me.util.security.entity;import java.util.ArrayList;import java.util.Collection;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Set;import org.apache.commons.lang.StringUtils;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.SimpleGrantedAuthority;import org.springframework.security.core.userdetails.UserDetails; public class User implements UserDetails {private static final long serialVersionUID = 8026813053768023527L; private String account;private String name;private String password;private boolean disabled; private Set<Role> roles; private Map<String, List<Resource>> roleResources;/** * The default constructor */public User() {}/** * Returns the authorites string * * eg. * downpour --- ROLE_ADMIN,ROLE_USER * robbin --- ROLE_ADMIN * * @return */public String getAuthoritiesString() { List<String> authorities = new ArrayList<String>(); for(GrantedAuthority authority : this.getAuthorities()) { authorities.add(authority.getAuthority()); } return StringUtils.join(authorities, ",");}@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {// 根据自定义逻辑来返回用户权限,如果用户权限返回空或者和拦截路径对应权限不同,验证不通过if(!roles.isEmpty()){List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();GrantedAuthority au = new SimpleGrantedAuthority("ROLE_USER");list.add(au);return list;}return null;}/* * 密码 */public String getPassword() {return password;}/* * 用户名 */public String getUsername() {return name;}/* *帐号是否不过期,false则验证不通过 */public boolean isAccountNonExpired() {return true;}/* * 帐号是否不锁定,false则验证不通过 */public boolean isAccountNonLocked() {return true;}/* * 凭证是否不过期,false则验证不通过 */public boolean isCredentialsNonExpired() {return true;}/* * 该帐号是否启用,false则验证不通过 */public boolean isEnabled() {return !disabled;} /** * @return the name */public String getName() {return name;}/** * @return the disabled */public boolean isDisabled() {return disabled;}/** * @return the roles */public Set<Role> getRoles() {return roles;}/** * @return the roleResources */public Map<String, List<Resource>> getRoleResources() {// init roleResources for the first timeSystem.out.println("---------------------------------------------------");if(this.roleResources == null) {this.roleResources = new HashMap<String, List<Resource>>();for(Role role : this.roles) {String roleName = role.getRoleName();Set<Resource> resources = role.getResources();for(Resource resource : resources) {String key = roleName + "_" + resource.getType();if(!this.roleResources.containsKey(key)) {this.roleResources.put(key, new ArrayList<Resource>());}this.roleResources.get(key).add(resource);}}}return this.roleResources;} /** * @param name the name to set */public void setName(String name) {this.name = name;}/** * @param password the password to set */public void setPassword(String password) {this.password = password;}/** * @param disabled the disabled to set */public void setDisabled(boolean disabled) {this.disabled = disabled;}/** * @param roles the roles to set */public void setRoles(Set<Role> roles) {this.roles = roles;}public String getAccount() {return account;}public void setAccount(String account) {this.account = account;}public void setRoleResources(Map<String, List<Resource>> roleResources) {this.roleResources = roleResources;}}
3.实现动态过滤用户权限
<custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="securityInterceptor"/>在spring-security配置文件中添加如下配置
<!-- 自定义拦截器 --><beans:bean id="securityInterceptor" class="com.ultrapower.me.util.security.interceptor.SecurityInterceptor"><beans:property name="authenticationManager" ref="authenticationManager"/> <beans:property name="accessDecisionManager" ref="mesecurityAccessDecisionManager"/> <beans:property name="securityMetadataSource" ref="secureResourceFilterInvocationDefinitionSource" /></beans:bean><!-- 获取访问url对应的所有权限 --><beans:bean id="secureResourceFilterInvocationDefinitionSource" class="com.ultrapower.me.util.security.interceptor.SecureResourceFilterInvocationDefinitionSource" /><!-- 校验用户的权限是否足够 --><beans:bean id="mesecurityAccessDecisionManager" class="com.ultrapower.me.util.security.interceptor.SecurityAccessDecisionManager" />
package com.ultrapower.me.util.security.interceptor;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import org.springframework.security.access.SecurityMetadataSource;import org.springframework.security.access.intercept.AbstractSecurityInterceptor;import org.springframework.security.access.intercept.InterceptorStatusToken;import org.springframework.security.web.FilterInvocation;import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;public class SecurityInterceptor extends AbstractSecurityInterceptor implements Filter{//配置文件注入 private FilterInvocationSecurityMetadataSource securityMetadataSource;public FilterInvocationSecurityMetadataSource getSecurityMetadataSource() {return securityMetadataSource;}public void setSecurityMetadataSource(FilterInvocationSecurityMetadataSource securityMetadataSource) {this.securityMetadataSource = securityMetadataSource;}@Overridepublic void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {// TODO Auto-generated method stub\FilterInvocation fi = new FilterInvocation(request, response, chain);//fi里面有一个被拦截的url //里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限 //再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够 InterceptorStatusToken token = super.beforeInvocation(fi); try { //执行下一个拦截器 fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); } finally { super.afterInvocation(token, null); } }@Overridepublic void init(FilterConfig arg0) throws ServletException {// TODO Auto-generated method stub}@Overridepublic Class<?> getSecureObjectClass() {// TODO Auto-generated method stubreturn FilterInvocation.class; }@Overridepublic SecurityMetadataSource obtainSecurityMetadataSource() {// TODO Auto-generated method stubreturn this.securityMetadataSource; }@Overridepublic void destroy() {// TODO Auto-generated method stub}}
登陆后,每次访问资源都会被这个拦截器拦截,会执行doFilter这个方法,这个方法调用了invoke方法,其中fi断点显示是一个url(可能重写了toString方法吧,但是里面还有一些方法的),最重要的是beforeInvocation这个方法,它首先会调用MyInvocationSecurityMetadataSource类的getAttributes方法获取被拦截url所需的权限,在调用MyAccessDecisionManager类decide方法判断用户是否够权限。弄完这一切就会执行下一个拦截器。
/** * */package com.ultrapower.me.util.security.interceptor;import java.util.ArrayList;import java.util.Collection;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import javax.servlet.ServletContext;import org.springframework.beans.factory.InitializingBean;import org.springframework.security.access.ConfigAttribute;import org.springframework.security.access.SecurityConfig;import org.springframework.security.web.FilterInvocation;import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;import org.springframework.util.AntPathMatcher;import org.springframework.util.PathMatcher;public class SecureResourceFilterInvocationDefinitionSource implements FilterInvocationSecurityMetadataSource, InitializingBean { private PathMatcher matcher; private static Map<String, Collection<ConfigAttribute>> map = new HashMap<String, Collection<ConfigAttribute>>(); /* * 初始化用户权限,为了简便操作没有从数据库获取 * 实际操作可以从数据库中获取所有资源路径url所对应的权限 */ public void afterPropertiesSet() throws Exception { this.matcher = new AntPathMatcher();//用来匹配访问资源路径 Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>(); ConfigAttribute ca = new SecurityConfig("ROLE_USER"); atts.add(ca); map.put("/jsp/index/main.jsp", atts); Collection<ConfigAttribute> attsno =new ArrayList<ConfigAttribute>(); ConfigAttribute cano = new SecurityConfig("ROLE_NO"); attsno.add(cano); map.put("/http://blog.csdn.net/u012367513/article/details/other.jsp", attsno); } @Overridepublic Collection<ConfigAttribute> getAttributes(Object object)throws IllegalArgumentException {// TODO Auto-generated method stub FilterInvocation filterInvocation = (FilterInvocation) object; String requestURI = filterInvocation.getRequestUrl(); //循环资源路径,当访问的Url和资源路径url匹配时,返回该Url所需要的权限 for(Iterator<Map.Entry<String, Collection<ConfigAttribute>>> iter = map.entrySet().iterator(); iter.hasNext();) { Map.Entry<String, Collection<ConfigAttribute>> entry = iter.next(); String url = entry.getKey(); if(matcher.match(url, requestURI)) { return map.get(requestURI); } } return null;}@Overridepublic Collection<ConfigAttribute> getAllConfigAttributes() {// TODO Auto-generated method stubreturn null;}/* (non-Javadoc) * @see org.springframework.security.intercept.ObjectDefinitionSource#getConfigAttributeDefinitions() */@SuppressWarnings("rawtypes")public Collection getConfigAttributeDefinitions() { return null; } /* (non-Javadoc) * @see org.springframework.security.intercept.ObjectDefinitionSource#supports(java.lang.Class) */public boolean supports(@SuppressWarnings("rawtypes") Class clazz) { return true; } /** * * @param filterInvocation * @return */ @SuppressWarnings("unchecked")private Map<String, String> getUrlAuthorities(org.springframework.security.web.FilterInvocation filterInvocation) { ServletContext servletContext = filterInvocation.getHttpRequest().getSession().getServletContext(); return (Map<String, String>)servletContext.getAttribute("urlAuthorities"); }}
mesecurityAccessDecisionManager实现
package com.ultrapower.me.util.security.interceptor;import java.util.Collection;import java.util.Iterator;import org.springframework.security.access.AccessDecisionManager;import org.springframework.security.access.AccessDeniedException;import org.springframework.security.access.ConfigAttribute;import org.springframework.security.access.SecurityConfig;import org.springframework.security.authentication.InsufficientAuthenticationException;import org.springframework.security.core.Authentication;import org.springframework.security.core.GrantedAuthority;public class SecurityAccessDecisionManager implements AccessDecisionManager { /** * 检查用户是否够权限访问资源 * authentication 是从spring的全局缓存SecurityContextHolder中拿到的,里面是用户的权限信息 * object 是url * configAttributes 所需的权限 * @see org.springframework.security.access.AccessDecisionManager#decide(org.springframework.security.core.Authentication, java.lang.Object, java.util.Collection) */@Overridepublic void decide(Authentication authentication, Object object,Collection<ConfigAttribute> configAttributes)throws AccessDeniedException, InsufficientAuthenticationException {// 对应url没有权限时,直接跳出方法 if(configAttributes == null){ return; } Iterator<ConfigAttribute> ite=configAttributes.iterator(); //判断用户所拥有的权限,是否符合对应的Url权限,如果实现了UserDetailsService,则用户权限是loadUserByUsername返回用户所对应的权限 while(ite.hasNext()){ ConfigAttribute ca=ite.next(); String needRole=((SecurityConfig)ca).getAttribute(); for(GrantedAuthority ga : authentication.getAuthorities()){ System.out.println(":::::::::::::"+ga.getAuthority()); if(needRole.equals(ga.getAuthority())){ return; } } } //注意:执行这里,后台是会抛异常的,但是界面会跳转到所配的access-denied-page页面 throw new AccessDeniedException("no right"); }@Overridepublic boolean supports(ConfigAttribute attribute) {return true;}@Overridepublic boolean supports(Class<?> clazz) {return true;}}
4.实现AuthenticationProvider,自定义参数验证
/** * 凭证,用户密码 */@Overridepublic Object getCredentials() {return password;}/** * 当事人,登录名 用户Id */@Overridepublic Object getPrincipal() {return userID;}
/** * 返回用户所属权限 */@Overridepublic Collection<GrantedAuthority> getAuthorities() {return this.accesses;}@Overridepublic Object getCredentials() {return null;}@Overridepublic Object getDetails() {return null;}/** * 登录名称 */@Overridepublic Object getPrincipal() {return loginName;}/** * 是否认证 */@Overridepublic boolean isAuthenticated() {return this.authenticated;}/** * 设置是否认证字段 */@Overridepublic void setAuthenticated(boolean isAuthenticated)throws IllegalArgumentException {this.authenticated=isAuthenticated;}
@SuppressWarnings("unchecked")@Overridepublic Authentication authenticate(Authentication authentication)throws AuthenticationException {PassCardAuthenticationToken token=(PassCardAuthenticationToken)authentication;/* * 这里进行逻辑认证操作,可以获取token中的属性来自定义验证逻辑,代码验证逻辑可以不用管 * 如果使用UserDetailsService的实现类来验证,就只能获取userName,不够灵活 */if(token.getUserID()!=null&&token.getPassword()!=null){User user=(User)this.getDao().executeQueryUnique("User.loadByLoginName", QueryCmdType.QUERY_NAME, token.getUserID());String password=token.getPassword();if(this.passwordEncoder!=null){password=this.passwordEncoder.encodePassword(password, null);}if(!password.equalsIgnoreCase(user.getPassword())){token.setErrCode("2");return null;}if( token.isEnablePasscard() && usePassCard ){//token中激活密码卡且系统使用密码卡int position1=((token.getRow1()-1)*7)+token.getColumn1();int position2=((token.getRow2()-1)*7)+token.getColumn2();//System.out.println( "---pos:"+position1+"---"+position2 );if(user.getPassCardId()==null){token.setErrCode("10");return null;}PassCard passcard=this.passCardDao.findById(user.getPassCardId(), false);if(passcard==null||passcard.getStatus()==PassCardHelper.STATUS_CANCEL ){token.setErrCode("10");return null;}if(passcard.getConfusedContent()==null || passcard.getConfusedContent().length()<7*7*32 ){token.setErrCode("10");return null;}String content=passcard.getConfusedContent();int perLen=content.length()/49;String str1=content.substring((position1-1)*perLen, position1*perLen);String str2=content.substring((position2-1)*perLen, position2*perLen);String inputStr1=token.getCard1();String inputStr2=token.getCard2();if(this.passwordEncoder!=null){inputStr1 = md5.getMD5ofStr(md5.getMD5ofStr(inputStr1));inputStr2 = md5.getMD5ofStr(md5.getMD5ofStr(inputStr2));}if((!str1.equalsIgnoreCase(inputStr1))||(!str2.equalsIgnoreCase(inputStr2))){token.setErrCode("10");return null;}}user.setLastIp(token.getIp());user.setLastLogin(new Date());this.getDao().saveOrUpdate(user);user.setAuthenticated(true);/* * 导入一次角色权限,并且把权限set到User中,用于spring验证用户权限(getAuthorities方法) */List<UserRole> userRoles=(List<UserRole>)this.getDao().executeQueryList("UserRole.listRoleByUserID", QueryCmdType.QUERY_NAME, -1, -1, user.getId());Set<GrantedAuthority> accesses=new HashSet<GrantedAuthority>();for(UserRole ur:userRoles){accesses.add(ur.getRole());}user.getOrg().getOrgName();if(user.getOrg().getCertTypes()!=null) user.getOrg().getCertTypes().size();//延迟载入一下user.setAccesses(accesses);return user;}return null;}
/** * 如果此处验证不通过,是不会执行authentication方法的 */@Overridepublic boolean supports(Class<? extends Object> authentication) {return authentication.equals(PassCardAuthenticationToken.class);}
4.定义filter,实现AbstractAuthenticationProcessingFilter的attemptAuthentication方法,用于获取在登录页面传递过来的参数,spring默认只获取userName(j_username),password(j_username),而且实现UserDetailsService时只传递username
import java.io.IOException;import java.util.Date;import javax.servlet.ServletException;import javax.servlet.http.Cookie;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import org.apache.log4j.Logger;import org.springframework.security.core.Authentication;import org.springframework.security.core.AuthenticationException;import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;import org.springframework.util.StringUtils;import cn.edu.jszg.cert.user.UserLog;import cn.edu.jszg.cert.user.UserLogService;import cn.edu.jszg.cert.web.WebApplicationConfiguration;import cn.edu.jszg.cert.web.controller.portal.auth.RemoteDataValidator;import com.google.code.kaptcha.servlet.KaptchaServlet;public class PasscardAuthenticationProcessingFilter extendsAbstractAuthenticationProcessingFilter {private String successPage = "/home/admin/index";private String failurePage = "/public/adminLoginEntry";private boolean forward = false;private boolean useVerifyCode=true;private String certLoginUrl;static Logger logger = Logger.getLogger(PasscardAuthenticationProcessingFilter.class);private WebApplicationConfiguration config;private UserLogService userLogService;public void setConfig(WebApplicationConfiguration config) {this.config = config;}/** * 实现AbstractAuthenticationProcessingFilter的有参构造 * 没记错的话,相当于该filter的访问路径 */protected PasscardAuthenticationProcessingFilter() {super("/adminLoginCheck");}public void setUseVerifyCode(boolean useVerifyCode) {this.useVerifyCode = useVerifyCode;}public void setUserLogService(UserLogService userLogService) {this.userLogService = userLogService;}public boolean validate(HttpServletRequest request) {String userId = request.getParameter("username");String md2 = request.getParameter("m");String l = request.getParameter("l");if (userId == null || md2 == null || l == null) {return false;}long longTime = Long.parseLong(l);if (longTime < new Date().getTime()) {return false;}try {String md1 = RemoteDataValidator.genExamMd5Digest(userId, longTime);if (md1.equals(md2))return true;} catch (Exception e) {//e.printStackTrace();}return false;}/** * 可以通过request获取页面传递过来的参数,并且set到相应的token中 */@Overridepublic Authentication attemptAuthentication(HttpServletRequest request,HttpServletResponse response) throws AuthenticationException,IOException, ServletException {//logger.warn("-----------------start证书登录用户----------");HttpSession s = request.getSession(true);PassCardAuthenticationToken token = new PassCardAuthenticationToken();String verifyCode = request.getParameter("verifyCode");String userID = request.getParameter("username");//....此处省略获取参数,并且验证、赋值的逻辑Authentication auth = null;try {//此处调用getAuthenticationManager的authenticate方法,当supports方法返回true时执行authenticate方法auth = this.getAuthenticationManager().authenticate(token);//此处为登录成功后,相应的处理逻辑if (auth == null || !auth.isAuthenticated()) {s.setAttribute("__login_error", token.getErrCode());} else {s.removeAttribute("__login_error");s.removeAttribute("__login_username");s.removeAttribute("__cert_userid");if( token.isEnablePasscard()) {s.removeAttribute("__passcard_row1");s.removeAttribute("__passcard_row2");s.removeAttribute("__passcard_column1");s.removeAttribute("__passcard_column2");}}} catch (AuthenticationException e) {s.setAttribute("__login_error", token.getErrCode());throw e;}return auth;}public void setSuccessPage(String successPage) {this.successPage = successPage;}public void setFailurePage(String failurePage) {this.failurePage = failurePage;}public void setForward(boolean forward) {this.forward = forward;}public void setCertLoginUrl(String certLoginUrl) {this.certLoginUrl = certLoginUrl;}@Overridepublic void afterPropertiesSet() {super.afterPropertiesSet();/**该处理器实现了AuthenticationSuccessHandler, AuthenticationFailureHandler*用于处理登录成功或者失败后,跳转的界面*/AuthenticationResultHandler handler = new AuthenticationResultHandler();handler.setForward(forward);handler.setLoginFailurePage(failurePage);handler.setLoginSuccessPage(successPage);handler.setCertLoginUrl(certLoginUrl);//设置父类中的处理器this.setAuthenticationSuccessHandler(handler);this.setAuthenticationFailureHandler(handler);}}
最后为spring-security配置文件中的配置,需要添加authentication-provider的引用,和filter的配置
<security:authentication-manager alias="authenticationManager"><!-- 注意,这里仅仅是系统默认的认证机制,请在正式系统中明确知道其功能再使用 --><security:authentication-provider ref="acocunt_defaultAnthentiactionProvider"/><security:authentication-provider ref="registrationService"/><security:authentication-provider ref="enrollmentService"/><security:authentication-provider ref="userService"/></security:authentication-manager><bean id="passcard_filter" class="cn.edu.jszg.cert.security.PasscardAuthenticationProcessingFilter"><property name="authenticationManager" ref="authenticationManager"/><property name="useVerifyCode" value="true"/><property name="failurePage" value="/portal/home/auth/"></property><property name="config" ref="webAppConfig"/><property name="userLogService" ref="userLogService" /><property name="certLoginUrl" value="${cert.login.url}"/></bean>还要在http中添加<security:custom-filter ref="passcard_filter" after="SECURITY_CONTEXT_FILTER"/>
- spring security四种实现方式
- spring security四种实现方式
- Spring Security 四种使用方式
- Spring实现AOP的四种方式
- spring实现注入的四种方式
- Spring实现AOP的四种方式
- Spring实现AOP的四种方式
- spring 实现AOP的四种方式
- 实现spring事务的四种方式
- spring 实现AOP的四种方式
- 实现spring事务的四种方式
- Spring AOP四种实现方式
- Spring 实现AOP的四种方式
- Spring之AOP四种实现方式
- spring AOP四种实现方式
- spring security(四)
- Spring Security教程(四)
- spring security 多登陆入口实现方式 以及对spring security认证流程的理解
- 拖动元素
- 如何动态调用 C 函数
- 【SIP基础】SIP协议中只有请求才有的头域
- Material之Behavior(1)
- Android字母导航示例
- spring security四种实现方式
- hinbernate懒加载异常org.hibernate.LazyInitializationException: could not initialize proxy - no Session
- 关于react性能优化的一些技巧(持续更新)
- 计网--TCP三挥四握&TCP与UDP的区别
- 一道算法题
- openwrt上pptp方式vpn的支持
- ActionBar下拉式导航
- 生产者消费者模型
- 多态之抽象类与虚方法的相似点及不同点