spring security四种实现方式

spring security四种实现方式springsecuri 实现方式大致可以分为这几种 1 配置文件实现 只需要在配置文件中指定拦截的 url 所需要权限 配置 userDetailsS 指定用户名 密码 对应权限 就可以实现 2 实现 UserDetailsS loadUserByUs StringuserNa 方法 根据 userName 来实现自己的业务逻辑返回 User

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

 
   
    
    
     
     
    
    
     
      
      
       
      
     
    
   

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

providers集合中的各个AuthenticationProvider接口实现类中的authenticate(Authentication authentication)方法进行验证,由此可见,真正的验证逻辑是由各个AuthenticationProvider接口实现类来完成的。DaoAuthenticationProvider类是默认情况下注入的一个AuthenticationProvider接口实现类

4.provider的实现类在验证用户时,会调用userDetailsService的实现类的loadUserByUsername方法来获取用户信息,

首先spring-security配置文件

 
   
   
    
    
     
     
     
     
     
     
     
     
     
    
    
     
     
      
      
     
    
    
    
    
    
  

userDetailsService实现:

/ * */ package com.up.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.up.me.util.Constants; import com.up.me.util.dbDao.SpringBeanUtil; import com.up.me.util.security.SecurityManager; import com.up.me.util.security.entity.Resource; import com.up.me.util.security.entity.Role; import com.up.me.util.security.entity.User; import com.up.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 
  
    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 
   
     roles = new HashSet 
    
      () ; Role role = new Role(); role.setRoleid("ROLE_USER"); role.setRoleName("ROLE_USER"); Set 
     
       resources=new HashSet 
      
        () ; 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不为空,则验证通过 } } 
       
      
     
    
  

/ * */ package com.up.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 = L; private String account; private String name; private String password; private boolean disabled; private Set 
  
    roles; private Map 
   
     > roleResources; / * The default constructor */ public User() { } / * Returns the authorites string * * eg. * downpour --- ROLE_ADMIN,ROLE_USER * robbin --- ROLE_ADMIN * * @return */ public String getAuthoritiesString() { List 
    
      authorities = new ArrayList 
     
       (); for(GrantedAuthority authority : this.getAuthorities()) { authorities.add(authority.getAuthority()); } return StringUtils.join(authorities, ","); } @Override public Collection 
       getAuthorities() { // 根据自定义逻辑来返回用户权限,如果用户权限返回空或者和拦截路径对应权限不同,验证不通过 if(!roles.isEmpty()){ List 
      
        list = new ArrayList 
       
         (); 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 
        
          getRoles() { return roles; } / * @return the roleResources */ public Map 
         
           > getRoleResources() { // init roleResources for the first time System.out.println("---------------------------------------------------"); if(this.roleResources == null) { this.roleResources = new HashMap 
          
            >(); for(Role role : this.roles) { String roleName = role.getRoleName(); Set 
           
             resources = role.getResources(); for(Resource resource : resources) { String key = roleName + "_" + resource.getType(); if(!this.roleResources.containsKey(key)) { this.roleResources.put(key, new ArrayList 
            
              ()); } 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 
             
               roles) { this.roles = roles; } public String getAccount() { return account; } public void setAccount(String account) { this.account = account; } public void setRoleResources(Map 
              
                > roleResources) { this.roleResources = roleResources; } } 
               
              
             
            
           
          
         
        
       
      
     
    
  

3.实现动态过滤用户权限

在spring-security配置文件的http标签中添加如下配置
 
   

在spring-security配置文件中添加如下配置

 

 
     
     
      
      
      
     
     
     
     
     

 

securityInterceptor继承AbstractSecurityInterceptor过滤器,实现Filter过滤器
package com.up.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; } @Override public 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); } } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } @Override public Class     getSecureObjectClass() { // TODO Auto-generated method stub return FilterInvocation.class; } @Override public SecurityMetadataSource obtainSecurityMetadataSource() { // TODO Auto-generated method stub return this.securityMetadataSource; } @Override public void destroy() { // TODO Auto-generated method stub } } 

登陆后,每次访问资源都会被这个拦截器拦截,会执行doFilter这个方法,这个方法调用了invoke方法,其中fi断点显示是一个url(可能重写了toString方法吧,但是里面还有一些方法的),最重要的是beforeInvocation这个方法,它首先会调用MyInvocationSecurityMetadataSource类的getAttributes方法获取被拦截url所需的权限,在调用MyAccessDecisionManager类decide方法判断用户是否够权限。弄完这一切就会执行下一个拦截器。

secureResourceFilterInvocationDefinitionSource实现
/ * */ package com.up.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         > map = new HashMap           >(); /* * 初始化用户权限,为了简便操作没有从数据库获取 * 实际操作可以从数据库中获取所有资源路径url所对应的权限 */ public void afterPropertiesSet() throws Exception { this.matcher = new AntPathMatcher();//用来匹配访问资源路径 Collection             atts = new ArrayList               (); ConfigAttribute ca = new SecurityConfig("ROLE_USER"); atts.add(ca); map.put("/jsp/index/main.jsp", atts); Collection                 attsno =new ArrayList                   (); ConfigAttribute cano = new SecurityConfig("ROLE_NO"); attsno.add(cano); map.put("/http://blog.csdn.net/u0/article/details/other.jsp", attsno); } @Override public Collection                     getAttributes(Object object) throws IllegalArgumentException { // TODO Auto-generated method stub FilterInvocation filterInvocation = (FilterInvocation) object; String requestURI = filterInvocation.getRequestUrl(); //循环资源路径,当访问的Url和资源路径url匹配时,返回该Url所需要的权限 for(Iterator                       >> iter = map.entrySet().iterator(); iter.hasNext();) { Map.Entry                         > entry = iter.next(); String url = entry.getKey(); if(matcher.match(url, requestURI)) { return map.get(requestURI); } } return null; } @Override public Collection                           getAllConfigAttributes() { // TODO Auto-generated method stub return 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                             getUrlAuthorities(org.springframework.security.web.FilterInvocation filterInvocation) { ServletContext servletContext = filterInvocation.getHttpRequest().getSession().getServletContext(); return (Map                               )servletContext.getAttribute("urlAuthorities"); } }                                                                                                                  

mesecurityAccessDecisionManager实现

package com.up.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) */ @Override public void decide(Authentication authentication, Object object, Collection         configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { // 对应url没有权限时,直接跳出方法 if(configAttributes == null){ return; } Iterator           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"); } @Override public boolean supports(ConfigAttribute attribute) { return true; } @Override public boolean supports(Class       clazz) { return true; } }         

 

4.实现AuthenticationProvider,自定义参数验证

这种验证以前项目用过,现在没有写示例代码,先写下大概流程和需要用到的类
这种验证的好处:可以在自定义登录界面添加登录时需要的参数,如多个验证码等、可以修改默认登录名称和密码的参数名
整体流程:
1.用户登录时,先经过自定义的passcard_filter过滤器,该过滤器继承了AbstractAuthenticationProcessingFilter,并且绑定了登录失败和成功时需要的处理器(跳转页面使用)
2.执行attemptAuthentication方法,可以通过request获取登录页面传递的参数,实现自己的逻辑,并且把对应参数set到AbstractAuthenticationToken的实现类中
3.验证逻辑走完后,调用 this.getAuthenticationManager().authenticate(token);方法,执行AuthenticationProvider的实现类的supports方法
4.如果返回true则继续执行authenticate方法
5.在authenticate方法中,首先可以根据用户名获取到用户信息,再者可以拿自定义参数和用户信息做逻辑验证,如密码的验证
6.自定义验证通过以后,获取用户权限set到User中,用于springSecurity做权限验证
7.this.getAuthenticationManager().authenticate(token)方法执行完后,会返回Authentication,如果不为空,则说明验证通过
8.验证通过后,可实现自定义逻辑操作,如记录cookie信息
9.attemptAuthentication方法执行完成后,由springSecuriy来进行对应权限验证,成功于否会跳转到相对应处理器设置的界面。
1.自定义PassCardAuthenticationToken类,继承AbstractAuthenticationToken类,用于定义参数,需要实现的方法
/ * 凭证,用户密码 */ @Override public Object getCredentials() { return password; } / * 当事人,登录名 用户Id */ @Override public Object getPrincipal() { return userID; }

 

2.User类要实现Authentication,需要实现的方法
/ * 返回用户所属权限 */ @Override public Collection           getAuthorities() { return this.accesses; } @Override public Object getCredentials() { return null; } @Override public Object getDetails() { return null; } / * 登录名称 */ @Override public Object getPrincipal() { return loginName; } / * 是否认证 */ @Override public boolean isAuthenticated() { return this.authenticated; } / * 设置是否认证字段 */ @Override public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { this.authenticated=isAuthenticated; }     

 

3.需要userService实现AuthenticationProvider的 authenticate(Authentication authentication)方法
  

@SuppressWarnings("unchecked") @Override public 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 
    
      userRoles=(List 
     
       )this.getDao().executeQueryList("UserRole.listRoleByUserID", QueryCmdType.QUERY_NAME, -1, -1, user.getId()); Set 
      
        accesses=new HashSet 
       
         (); 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; } 
        
       
      
    

   重写supports(Class
authentication)方法,authentication要
/ * 如果此处验证不通过,是不会执行authentication方法的 */ @Override public boolean supports(Class 
     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 extends AbstractAuthenticationProcessingFilter { 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中 */ @Override public 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; } @Override public 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的配置

                                                                                      

还要在http中添加


 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/198443.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月26日 下午3:12
下一篇 2026年3月26日 下午3:13


相关推荐

  • ewebeditor漏洞大全

    ewebeditor漏洞大全1:默认管理后台: http://www.backlion.com/ewebeditor/admin_login.asp后台如果能进入:可点击样式管理:standard拷贝一份(直接修改改不了)在拷贝的一份里加入图片类型(asaaaspsp)  然后点预览在编辑器里点设计   然后直接上传asa大马.上传后在代码里可以看到马的位置!

    2022年7月14日
    76
  • ScheduledExecutorService

    ScheduledExecutorService任务调度(三)——Timer的替代品ScheduledExecutorService简介标签:任务调度TimerScheduledExecutorSer2015-08-0619:075704人阅读评论(2)收藏举报分类:【定时任务分时器】(3)作者同类文章X【java基础】(29)

    2022年5月5日
    47
  • 凸包详解

    凸包详解首先讲解一下凸包的概念用比较抽象的说就是 在一个实数向量空间 V 中 对于给定集合 X 所有包含 X 的凸集的交集 S 被称为 X 的凸包 X 的凸包可以用 X 内所有点 X1 Xn 的凸组合来构造 简单来说 给你一个点集 Q 你可以把 Q 中的每个点想象成一块木板上的铁钉 而点集 Q 的凸包就是包围了所有铁钉的一条拉紧了橡皮绳所构成的形状 如图 求凸包可以用 Craham 扫描法 它用了一种

    2026年3月19日
    3
  • vb语言与测量程序设计吕翠华主编课后答案_c程序设计第五版答案第四章

    vb语言与测量程序设计吕翠华主编课后答案_c程序设计第五版答案第四章第一节数据类型VB中提供了以下11中基本的数据类型:一、数值型二、字符串三、日期型1.界面设计2.代码 1 PrivateSubCommand1_Click() 2 Timer1.Enabled=True 3 EndSub 4 5 PrivateSu…

    2022年10月6日
    5
  • CentOS下Apache配置虚拟主机[通俗易懂]

    CentOS下Apache配置虚拟主机[通俗易懂]有时候我们往往一个服务器会运行多个应用,此时就需要给每个应用创建虚拟主机了,这里我创建三个文件夹,分别运行三个页面:

    2025年11月27日
    4
  • ntp网络时间协议_ntp网络时间协议特性

    ntp网络时间协议_ntp网络时间协议特性NTP是网络时间协议(NetworkTimeProtocol),它是用来同步网络中各个计算机的时间的协议。  原理:NTP要提供准确的时间,就必须有准确的时间来源,那可以用格林尼治时间吗?答案是否定的。因为格林尼治时间是以地球自转为基础的时间计量系统,但是地球每天的自转是有些不规则的,而且正在缓慢加速,因此,格林尼治时间已经不再被作为标准时间使用。新的标准时间,是由原子钟报时的

    2022年10月12日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号