Spring security+rememberme学习笔记(1)

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private CustomUserDetailsService detailsService;

	@Autowired
	private SignedUsernamepasswordAuthenticationProvider provider;
	@Autowired
	private RememberMeAuthenticationProvider RememberMeprovider;

	@Autowired
	private AuthenticationManager authenticationManager;
	@Autowired
	private FilterInvocationSecurityMetadataSource securityMetadataSource;

	@Resource
	private SessionRegistry sessionRegistry;

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		//添加用户验证
		auth.authenticationProvider(provider);
		auth.authenticationProvider(RememberMeprovider);
		// 不删除凭据,以便记住用户
		auth.eraseCredentials(false);
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// 解决不允许显示在iframe的问题
		http.headers().frameOptions().disable();
		// 自定义过滤器

		MyFilterSecurityInterceptor filterSecurityInterceptor = new MyFilterSecurityInterceptor(securityMetadataSource,
				accessDecisionManager(), authenticationManager);
		// 在适当的地方加入
		// 此处可以加入logoutFilter
		http.addFilterAt(cuzLogoutFilter(), LogoutFilter.class);
		
		// 此处可以添加remmebermeAuth..FILTER
		http.addFilterAfter(rememberMeAuthenticationFilter(),
				 RememberMeAuthenticationFilter.class);
		// 添加UsernamePasswordAuthenticationFilter
				http.addFilterAt(myUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
		 //session并发控制过滤器
        http.addFilterAt(new ConcurrentSessionFilter(sessionRegistry,sessionInformationExpiredStrategy()),ConcurrentSessionFilter.class);
		
		
		// 此处可以添加filterSecurityInterceptor..FILTER
		// http.addFilterBefore(filterSecurityInterceptor,FilterSecurityInterceptor.class);
		AccessDeniedHandler accessDeniedHandler = new CustomAccessDeniedHandler("/error/illegalAccess");
		http	// .csrf().disable()//取消CSRF
				.authorizeRequests().antMatchers("/css/**").permitAll().antMatchers("/login").permitAll().anyRequest()// all
				.authenticated().and().formLogin().loginPage("/login").permitAll().defaultSuccessUrl("/home", true)
				.failureUrl("/login?error").and().logout().clearAuthentication(true).logoutUrl("/logout")
				.logoutSuccessUrl("/login").and().sessionManagement().invalidSessionUrl("/login").maximumSessions(1)
				.expiredUrl("/login").and().and().exceptionHandling().accessDeniedPage("/accessDenied")// .accessDeniedHandler(accessDeniedHandler)//拒绝访问时跳转
				.and()
		// .rememberMe()//启用记住我功能
		// .tokenValiditySeconds(2419200)//记住我四周
		// .key("manageKey")
		;

		// http.exceptionHandling().authenticationEntryPoint(new
		// LoginUrlAuthenticationEntryPoint("/login")).and().logout().logoutUrl("/logout").logoutSuccessUrl("/login").and().exceptionHandling().accessDeniedPage("/accessDenied");

		super.configure(http);
	}

	// logoutFilter
	@Bean
	public LogoutFilter cuzLogoutFilter() {
		CuzLogoutFilter filter = new CuzLogoutFilter("/login", customLogoutHandler());
		return filter;
	}

	public LogoutHandler[] customLogoutHandler() {

		return new LogoutHandler[] { new SecurityContextLogoutHandler(), new CustomLogoutHandler(),
				tokenBasedRememberMeServices() };
	}

	@Override
	public void configure(WebSecurity web) throws Exception {
		// 图片资源不拦截
		web.ignoring().antMatchers("/app/**");
		web.ignoring().antMatchers("/common/**");
		web.ignoring().antMatchers("/app/css/**");
		web.ignoring().antMatchers("*/images/**");
		web.ignoring().antMatchers("/app/js/**");
		web.ignoring().antMatchers("/plugins/**");
		web.ignoring().antMatchers("/favicon.ico");
		web.ignoring().antMatchers("/login/captcha");
		web.ignoring().antMatchers("/error/illegalAccess");
		super.configure(web);
	}

	// session失效跳转
	private SessionInformationExpiredStrategy sessionInformationExpiredStrategy() {
		return new SimpleRedirectSessionInformationExpiredStrategy("/login");
	}

	@Bean
	public SessionRegistry sessionRegistry() {
		return new CustomSessionRegistryImpl();
	}

	// SpringSecurity内置的session监听器
	@Bean
	public HttpSessionEventPublisher httpSessionEventPublisher() {
		return new HttpSessionEventPublisher();
	}

	/**
	 * 投票器
	 */
	/**
	 * AccessdecisionManager在Spring security中是很重要的。
	 * 
	 * 在验证部分简略提过了,所有的Authentication实现需要保存在一个GrantedAuthority对象数组中。 这就是赋予给主体的权限。
	 * GrantedAuthority对象通过AuthenticationManager 保存到
	 * Authentication对象里,然后从AccessDecisionManager读出来,进行授权判断。
	 * 
	 * Spring Security提供了一些拦截器,来控制对安全对象的访问权限,例如方法调用或web请求。
	 * 一个是否允许执行调用的预调用决定,是由AccessDecisionManager实现的。 这个 AccessDecisionManager
	 * 被AbstractSecurityInterceptor调用, 它用来作最终访问控制的决定。
	 * 这个AccessDecisionManager接口包含三个方法:
	 * 
	 * void decide(Authentication authentication, Object secureObject,
	 * List config) throws AccessDeniedException; boolean
	 * supports(ConfigAttribute attribute); boolean supports(Class clazz);
	 * 
	 * 从第一个方法可以看出来,AccessDecisionManager使用方法参数传递所有信息,这好像在认证评估时进行决定。
	 * 特别是,在真实的安全方法期望调用的时候,传递安全Object启用那些参数。 比如,让我们假设安全对象是一个MethodInvocation。
	 * 很容易为任何Customer参数查询MethodInvocation,
	 * 然后在AccessDecisionManager里实现一些有序的安全逻辑,来确认主体是否允许在那个客户上操作。
	 * 如果访问被拒绝,实现将抛出一个AccessDeniedException异常。
	 * 
	 * 这个 supports(ConfigAttribute) 方法在启动的时候被
	 * AbstractSecurityInterceptor调用,来决定AccessDecisionManager
	 * 是否可以执行传递ConfigAttribute。 supports(Class)方法被安全拦截器实现调用,
	 * 包含安全拦截器将显示的AccessDecisionManager支持安全对象的类型。
	 */
	private AbstractAccessDecisionManager accessDecisionManager() {
		List> decisionVoters = new ArrayList();
		decisionVoters.add(new AuthenticatedVoter());
		decisionVoters.add(new RoleVoter());// 角色投票器,默认前缀为ROLE_
		RoleVoter AuthVoter = new RoleVoter();
		AuthVoter.setRolePrefix("AUTH_");// 特殊权限投票器,修改前缀为AUTH_,用于自定义角色
		decisionVoters.add(AuthVoter);
		AbstractAccessDecisionManager accessDecisionManager = new AffirmativeBased(decisionVoters);//一票通过投票策略,还可以选用一票否决策略,多票通过策略,也可以自定义需求
		//CustomAccessDecisionManager accessDecisionManager1 = new CustomAccessDecisionManager();// 用自定义的一票通过投票策略//此处采用用户自定义的投票器
		//改成系统定义的策略器,因为自定义的虽然至此任意前缀的权限,但也意味着管理的复制性
		return accessDecisionManager;
	}

	@Bean
	@Override
	public AuthenticationManager authenticationManagerBean() {
		AuthenticationManager authenticationManager = null;
		try {
			authenticationManager = super.authenticationManagerBean();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return authenticationManager;
	}

	/**
	 * 验证异常处理器,登录失败后调用
	 *其配置进CuzUsernamePasswordAuthenticationFilter中
	 * @return
	 */
	private SimpleUrlAuthenticationFailureHandler simpleUrlAuthenticationFailureHandler() {
		return new SimpleUrlAuthenticationFailureHandler("/login");
	}

	/**
	 * 登录成功后跳转 如果需要根据不同的角色做不同的跳转处理,那么继承AuthenticationSuccessHandler重写方法
	 *其配置进CuzUsernamePasswordAuthenticationFilter中
	 * @return
	 */
	private SimpleUrlAuthenticationSuccessHandler authenticationSuccessHandler() {
		return new SimpleUrlAuthenticationSuccessHandler("/home");
	}

	@Bean
	public CuzUsernamePasswordAuthenticationFilter myUsernamePasswordAuthenticationFilter() throws Exception {
		CuzUsernamePasswordAuthenticationFilter myUsernamePasswordAuthenticationFilter = new CuzUsernamePasswordAuthenticationFilter();
		myUsernamePasswordAuthenticationFilter.setPostOnly(true);
		myUsernamePasswordAuthenticationFilter.setAuthenticationManager(this.authenticationManager());
		myUsernamePasswordAuthenticationFilter.setUsernameParameter("username");
		myUsernamePasswordAuthenticationFilter.setPasswordParameter("password");
		// myUsernamePasswordAuthenticationFilter.set
		// myUsernamePasswordAuthenticationFilter.setVerificationCodeParameter("verification_code");
		myUsernamePasswordAuthenticationFilter
				.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login", "POST"));
		myUsernamePasswordAuthenticationFilter.setAuthenticationFailureHandler(simpleUrlAuthenticationFailureHandler());
		myUsernamePasswordAuthenticationFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler());
		myUsernamePasswordAuthenticationFilter.setSessionAuthenticationStrategy(
				new CustomConcurrentSessionControlAuthenticationStrategy(sessionRegistry));
		myUsernamePasswordAuthenticationFilter.setRememberMeServices(tokenBasedRememberMeServices());
//		myUsernamePasswordAuthenticationFilter
		return myUsernamePasswordAuthenticationFilter;
	}

	public static class MyFilterSecurityInterceptor extends FilterSecurityInterceptor {
		//其作用在与在request中加入"__spring_security_filterSecurityInterceptor_filterApplied属性
		//同时管理调用资源文件对应的权限
		public MyFilterSecurityInterceptor(FilterInvocationSecurityMetadataSource securityMetadataSource,
				AccessDecisionManager accessDecisionManager, AuthenticationManager authenticationManager) {
			this.setSecurityMetadataSource(securityMetadataSource);// 加入资源管理器
			this.setAccessDecisionManager(accessDecisionManager);// 加入决策管理器
			this.setAuthenticationManager(authenticationManager);// 加入验证管理器

		}
	}

	@Bean
	public FilterInvocationSecurityMetadataSource MyFilterInvocationSecurityMetadataSource() {
		return new CustomInvocationSecurityMetadataSource();
	}

	// 配置remmeber me

	@Bean
	public TokenBasedRememberMeServices tokenBasedRememberMeServices() {
		// 自定义RememberMeService,可以加入数据库操作,比如当设置用户使用退出功能退出应用后,下次remmeberme功能不可用,当前系统未添加此功能
		TokenBasedRememberMeServices tbrms = new CustomTokenBasedRememberMeServices("_spring_security_Key",
				detailsService);
		// 设置cookie过期时间为2天
		tbrms.setTokenValiditySeconds(60 * 60 * 24 * 2);
		// 设置checkbox的参数名为rememberMe(默认为remember-me),注意如果是ajax请求,参数名不是checkbox的name而是在ajax的data里
		tbrms.setParameter("_spring_security_remember_me");
		tbrms.setCookieName("_spring_security_Key");
		return tbrms;
	}

	@Bean
	public RememberMeAuthenticationProvider rememberMeAuthenticationProvider() {
		RememberMeAuthenticationProvider rmap = new CustomRememberMeAuthenticationProvider("_spring_security_Key");

		return rmap;
	}

	@Bean
	public RememberMeAuthenticationFilter rememberMeAuthenticationFilter() throws Exception {
		// 自定义RememberMeAuthenticationFilter,可添加额外操作
		RememberMeAuthenticationFilter myFilter = new CuzRememberMeAuthenticationFilter(authenticationManager,
				tokenBasedRememberMeServices());
		return myFilter;
	}

}

安全配置文件,首先继承WebSecurityConfigurerAdapter类,相关的pom配置请查看spring网站的依赖。

@EnableWebSecurity和@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)加载class上,以便通知spring boot初始化时初始化相关的WebSecurity的bean.@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)是用来使能方法安全的,按自己需求看看是否需要。

然后就可以去具体配置了哈。

为了实现登录效验,我们实现相关filter,然后重载configure(HttpSecurity http),然后按照官方的fiter次序依次添加我们需要的fiter.在上面的代码片段中,fiter都是自定义的,也较容易,依次继承相关的fiter,写自己的实现就ok了。

我们通过spring官方网站了解知道,验证是通过auth..manager调用provider来实现的。因此,需要配置provider.

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//添加用户验证
auth.authenticationProvider(provider);
auth.authenticationProvider(RememberMeprovider);
// 不删除凭据,以便记住用户
auth.eraseCredentials(false);
}

我定义了两个provider.分别实现AuthenticationProvider接口,继承RememberMeAuthenticationProvider(spring自带的RememberMeAuthenticationProvider好像是空的哈)。

不多说,贴代码:

public class CustomRememberMeAuthenticationProvider  extends RememberMeAuthenticationProvider{

	
	public CustomRememberMeAuthenticationProvider(String key) {
		super(key);
	}

	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		if (!supports(authentication.getClass())) {
			return null;
		}
		if (super.getKey().hashCode() != ((RememberMeAuthenticationToken) authentication)
				.getKeyHash()) {
			throw new BadCredentialsException(
					messages.getMessage("RememberMeAuthenticationProvider.incorrectKey",
							"The presented RememberMeAuthenticationToken does not contain the expected key"));
		}

		return authentication;
	}
	
	public boolean supports(Class authentication) {
		return (RememberMeAuthenticationToken.class.isAssignableFrom(authentication));
	}
}
public class SignedUsernamepasswordAuthenticationProvider implements AuthenticationProvider  {
	
	 @Autowired
	 private CustomUserDetailsService userService;
	
	/**
     * 自定义验证方式
     */
	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		if (!supports(authentication.getClass())) {
			return null;
		}
		String username = authentication.getName();
	        String password = (String) authentication.getCredentials();
	        SigedUserDetails user = (SigedUserDetails) userService.loadUserByUsername(username);
	        if(user == null){
	            throw new BadCredentialsException("Username not found.");
	        }

	        //加密过程在这里体现
	        
	        ;//admin:ab4ad1624d29173c70d739c389e1daa3,Q123456W:2db436d701334d81c11ad8eb781e92c2
	        
	        if (!MD5Util.encrypt(password).equals(user.getPassword())) {
	        	
	            throw new BadCredentialsException("Wrong password.");
	        }
	        
	       
	        
	        Collection authorities = user.getAuthorities();
	        return new UsernamePasswordAuthenticationToken(user, password, authorities);
	}

	@Override
	public boolean supports(Class authentication) {
		// TODO Auto-generated method stub
		//return true;
		return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
	}
package com.iqibai.gmrm.config.security.sessionconfig;


import java.util.Iterator;
import java.util.List;


import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


import org.springframework.context.MessageSource;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.SpringSecurityMessageSource;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy;
import org.springframework.security.web.authentication.session.SessionAuthenticationException;
import org.springframework.util.Assert;


/**
 * Created by 为 on 2017-9-26
 */
public class CustomConcurrentSessionControlAuthenticationStrategy extends ConcurrentSessionControlAuthenticationStrategy {


    protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor();
    private final SessionRegistry sessionRegistry;
    private boolean exceptionIfMaximumExceeded = false;
    private int maximumSessions = 1;


    public CustomConcurrentSessionControlAuthenticationStrategy(SessionRegistry sessionRegistry) {
        super(sessionRegistry);
        Assert.notNull(sessionRegistry, "The sessionRegistry cannot be null");
        this.sessionRegistry = sessionRegistry;
    }


    public void onAuthentication(Authentication authentication, HttpServletRequest request, HttpServletResponse response) {
        List sessions = this.sessionRegistry.getAllSessions(authentication.getPrincipal(), false);
        int sessionCount = sessions.size();
        int allowedSessions = this.getMaximumSessionsForThisUser(authentication);
        if(sessionCount >= allowedSessions) {
            if(allowedSessions != -1) {
                if(sessionCount == allowedSessions) {
                    HttpSession session = request.getSession(false);
                    if(session != null) {
                        Iterator var8 = sessions.iterator();


                        while(var8.hasNext()) {
                            SessionInformation si = (SessionInformation)var8.next();
                            if(si.getSessionId().equals(session.getId())) {
                                return;
                            }
                        }
                    }
                }


                this.allowableSessionsExceeded(sessions, allowedSessions, this.sessionRegistry);
            }
        }
    }


    protected int getMaximumSessionsForThisUser(Authentication authentication) {
        return this.maximumSessions;
    }


    protected void allowableSessionsExceeded(List sessions, int allowableSessions, SessionRegistry registry) throws SessionAuthenticationException {
        if(!this.exceptionIfMaximumExceeded && sessions != null) {
            SessionInformation leastRecentlyUsed = null;
            Iterator var5 = sessions.iterator();


            while(true) {
                SessionInformation session;
                do {
                    if(!var5.hasNext()) {
                        leastRecentlyUsed.expireNow();
                        
                        ((CustomSessionRegistryImpl)sessionRegistry).addSessionInfo(leastRecentlyUsed.getSessionId(),leastRecentlyUsed);
                        return;
                    }


                    session = (SessionInformation)var5.next();
                } while(leastRecentlyUsed != null && !session.getLastRequest().before(leastRecentlyUsed.getLastRequest()));


                leastRecentlyUsed = session;
            }
        } else {
            throw new SessionAuthenticationException(this.messages.getMessage("ConcurrentSessionControlAuthenticationStrategy.exceededAllowed", new Object[]{Integer.valueOf(allowableSessions)}, "Maximum sessions of {0} for this principal exceeded"));
        }
    }


    public void setExceptionIfMaximumExceeded(boolean exceptionIfMaximumExceeded) {
        this.exceptionIfMaximumExceeded = exceptionIfMaximumExceeded;
    }


    public void setMaximumSessions(int maximumSessions) {
        Assert.isTrue(maximumSessions != 0, "MaximumLogins must be either -1 to allow unlimited logins, or a positive integer to specify a maximum");
        this.maximumSessions = maximumSessions;
    }


    public void setMessageSource(MessageSource messageSource) {
        Assert.notNull(messageSource, "messageSource cannot be null");
        this.messages = new MessageSourceAccessor(messageSource);
    }


}

@Slf4j
public class CustomSessionRegistryImpl  implements SessionRegistry, ApplicationListener {




   private static final String SESSIONIDS = "sessionIds";


   private static final String PRINCIPALS = "principals";


   @Autowired
   private RedisTemplate redisTemplate;


   
//   private final ConcurrentMap> principals = new ConcurrentHashMap();
//   private final Map sessionIds = new ConcurrentHashMap();


   public CustomSessionRegistryImpl() {
   }


   public List getAllPrincipals() {
       return new ArrayList(this.getPrincipalsKeySet());
   }


   public List getAllSessions(Object principal, boolean includeExpiredSessions) {
       Set sessionsUsedByPrincipal =  this.getPrincipals(((SigedUserDetails)principal).getUsername());
       if (sessionsUsedByPrincipal == null) {
           return Collections.emptyList();
       } else {
           List list = new ArrayList(sessionsUsedByPrincipal.size());
           Iterator var5 = sessionsUsedByPrincipal.iterator();


           while (true) {
               SessionInformation sessionInformation;
               do {
                   do {
                       if (!var5.hasNext()) {
                           return list;
                       }


                       String sessionId = (String) var5.next();
                       sessionInformation = this.getSessionInformation(sessionId);
                   } while (sessionInformation == null);
               } while (!includeExpiredSessions && sessionInformation.isExpired());


               list.add(sessionInformation);
           }
       }
   }


   public SessionInformation getSessionInformation(String sessionId) {
       Assert.hasText(sessionId, "SessionId required as per interface contract");
       return (SessionInformation) this.getSessionInfo(sessionId);
   }


   public void onApplicationEvent(SessionDestroyedEvent event) {
       String sessionId = event.getId();
       this.removeSessionInformation(sessionId);
   }


   public void refreshLastRequest(String sessionId) {
       Assert.hasText(sessionId, "SessionId required as per interface contract");
       SessionInformation info = this.getSessionInformation(sessionId);
       if (info != null) {
           info.refreshLastRequest();
       }


   }


   public void registerNewSession(String sessionId, Object principal) {
       Assert.hasText(sessionId, "SessionId required as per interface contract");
       Assert.notNull(principal, "Principal required as per interface contract");
       if (this.log.isDebugEnabled()) {
           this.log.debug("Registering session " + sessionId + ", for principal " + principal);
       }


       if (this.getSessionInformation(sessionId) != null) {
           this.removeSessionInformation(sessionId);
       }


       this.addSessionInfo(sessionId, new SessionInformation(principal, sessionId, new Date()));


//       this.sessionIds.put(sessionId, new SessionInformation(principal, sessionId, new Date()));
       Set sessionsUsedByPrincipal = (Set) this.getPrincipals(principal.toString());
       if (sessionsUsedByPrincipal == null) {
           sessionsUsedByPrincipal = new CopyOnWriteArraySet();
           Set prevSessionsUsedByPrincipal = (Set) this.putIfAbsentPrincipals(principal.toString(), sessionsUsedByPrincipal);
           if (prevSessionsUsedByPrincipal != null) {
               sessionsUsedByPrincipal = prevSessionsUsedByPrincipal;
           }
       }


       ((Set) sessionsUsedByPrincipal).add(sessionId);
       this.putPrincipals(principal.toString(), sessionsUsedByPrincipal);
       if (this.log.isTraceEnabled()) {
           this.log.trace("Sessions used by '" + principal + "' : " + sessionsUsedByPrincipal);
       }


   }


   public void removeSessionInformation(String sessionId) {
       Assert.hasText(sessionId, "SessionId required as per interface contract");
       SessionInformation info = this.getSessionInformation(sessionId);
       if (info != null) {
           if (this.log.isTraceEnabled()) {
               this.log.debug("Removing session " + sessionId + " from set of registered sessions");
           }


           this.removeSessionInfo(sessionId);
           Set sessionsUsedByPrincipal = (Set) this.getPrincipals(info.getPrincipal().toString());
           if (sessionsUsedByPrincipal != null) {
               if (this.log.isDebugEnabled()) {
                   this.log.debug("Removing session " + sessionId + " from principal's set of registered sessions");
               }


               sessionsUsedByPrincipal.remove(sessionId);
               if (sessionsUsedByPrincipal.isEmpty()) {
                   if (this.log.isDebugEnabled()) {
                       this.log.debug("Removing principal " + info.getPrincipal() + " from registry");
                   }


                   this.removePrincipal(((SigedUserDetails)info.getPrincipal()).getUsername());
               }


               if (this.log.isTraceEnabled()) {
                   this.log.trace("Sessions used by '" + info.getPrincipal() + "' : " + sessionsUsedByPrincipal);
               }


           }
       }
   }




   public void addSessionInfo(final String sessionId, final SessionInformation sessionInformation) {
       BoundHashOperations hashOperations = redisTemplate.boundHashOps(SESSIONIDS);
       hashOperations.put(sessionId, sessionInformation);
   }


   public SessionInformation getSessionInfo(final String sessionId) {
       BoundHashOperations hashOperations = redisTemplate.boundHashOps(SESSIONIDS);
       return hashOperations.get(sessionId);
   }


   public void removeSessionInfo(final String sessionId) {
       BoundHashOperations hashOperations = redisTemplate.boundHashOps(SESSIONIDS);
       hashOperations.delete(sessionId);
   }


   public Set putIfAbsentPrincipals(final String key, final Set set) {
       BoundHashOperations> hashOperations = redisTemplate.boundHashOps(PRINCIPALS);
       hashOperations.putIfAbsent(key, set);
       return hashOperations.get(key);
   }


   public void putPrincipals(final String key, final Set set) {
       BoundHashOperations> hashOperations = redisTemplate.boundHashOps(PRINCIPALS);
       hashOperations.put(key,set);
   }


   public Set getPrincipals(final String key) {
       BoundHashOperations> hashOperations = redisTemplate.boundHashOps(PRINCIPALS);
       return hashOperations.get(key);
   }


   public Set getPrincipalsKeySet() {
       BoundHashOperations> hashOperations = redisTemplate.boundHashOps(PRINCIPALS);
       return hashOperations.keys();
   }


   public void removePrincipal(final String key) {
       BoundHashOperations> hashOperations = redisTemplate.boundHashOps(PRINCIPALS);
       hashOperations.delete(key);
   }




}

贴代码真麻烦!这两个代码是实现分布式session的,如果没有这个需求可以去掉的。

注意,本人在用了这个session策略后,rememberme老重复登录,检查发现,需要在public class CuzRememberMeAuthenticationFilter extends RememberMeAuthenticationFilter实现时重载dofiter方法,然后在。。贴代码吧

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;


if (SecurityContextHolder.getContext().getAuthentication() == null) {
Authentication rememberMeAuth = getRememberMeServices().autoLogin(request,
response);


if (rememberMeAuth != null) {
// Attempt authenticaton via AuthenticationManager
try {
rememberMeAuth = authenticationManager.authenticate(rememberMeAuth);


// Store to SecurityContextHolder
SecurityContextHolder.getContext().setAuthentication(rememberMeAuth);
SigedUserDetails userdelail = (SigedUserDetails) rememberMeAuth.getPrincipal();
Collection authorities = userdelail.getAuthorities();
Authentication auth = new UsernamePasswordAuthenticationToken(
        userdelail.getUserName(), userdelail.getPassword(), authorities);




       SecurityContextHolder.getContext().setAuthentication(auth);
       SecurityContextHolder.getContext().setAuthentication(rememberMeAuth);
       CustomConcurrentSessionControlAuthenticationStrategy  sessionStrategy = new CustomConcurrentSessionControlAuthenticationStrategy(sessionRegistry);
       sessionStrategy.onAuthentication(auth, request, response);
       sessionStrategy.onAuthentication(rememberMeAuth, request, response);

onSuccessfulAuthentication(request, response, rememberMeAuth);


if (logger.isDebugEnabled()) {
logger.debug("SecurityContextHolder populated with remember-me token: '"
+ SecurityContextHolder.getContext().getAuthentication()
+ "'");
}


// Fire event
if (this.eventPublisher != null) {
eventPublisher
.publishEvent(new InteractiveAuthenticationSuccessEvent(
SecurityContextHolder.getContext()
.getAuthentication(), this.getClass()));
}


if (successHandler != null) {
successHandler.onAuthenticationSuccess(request, response,
rememberMeAuth);


return;
}


}
catch (AuthenticationException authenticationException) {
if (logger.isDebugEnabled()) {
logger.debug(
"SecurityContextHolder not populated with remember-me token, as "
+ "AuthenticationManager rejected Authentication returned by RememberMeServices: '"
+ rememberMeAuth
+ "'; invalidating remember-me token",
authenticationException);
}


rememberMeServices.loginFail(request, response);


onUnsuccessfulAuthentication(request, response,
authenticationException);
}
}


chain.doFilter(request, response);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("SecurityContextHolder not populated with remember-me token, as it already contained: '"
+ SecurityContextHolder.getContext().getAuthentication() + "'");
}


chain.doFilter(request, response);
}
}

把自己的user..token保存进去。就ok了。写这篇博客主要也是为了这个事情,当时弄了几天额。。。。

你可能感兴趣的:(spring,security,配置)