zoukankan      html  css  js  c++  java
  • spring security 5 session管理

    spring security 如何保存我们的登录信息。


    根据官方文档我们可以知道通过登录验证(AuthenticationProvider.authenticate(Authentication authentication)方法中验证,返回一个Authentication->UsernamePasswordAuthenticationToken(userDetails, password, authorities);)后,会将一个验证通过的实例Authentication放入安全上下文SecurityContextSecurityContext可从SecurityContextHolder中获得。
    Authentication信息包括:

    • principal -验证用户,通常为UserDetails实例(实际生产中实现该接口,通过数据库查询该信息)。
    • credentials -通常是密码。在许多情况下,将在验证用户身份后清除此内容,以确保它不会泄漏。
    • authorities -权限GrantedAuthority。 通常是角色或范围。

    验证通过后,后续需要登录用户信息可直接从Authentication获取。

    spring security 如何记录登录状态

    我们知道javaweb 通过jsession 会话id来确保同一个会话,同一个连接。在security中同样通过jSessionId来记录用户登录,每次请求到达服务端,会通过ConcurrentSessionFilter过滤器验证是否存在该session,不存在则不是登录状态。验证通过继续执行FilterChain后续的过滤器。
    ConcurrentSessionFilter部分源码

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest)req;
            HttpServletResponse response = (HttpServletResponse)res;
            HttpSession session = request.getSession(false);
            if (session != null) {
                SessionInformation info = this.sessionRegistry.getSessionInformation(session.getId());
                if (info != null) {
                    //session过期做退出登录处理
                    if (info.isExpired()) {
                        if (this.logger.isDebugEnabled()) {
                            this.logger.debug("Requested session ID " + request.getRequestedSessionId() + " has expired.");
                        }
    
                        this.doLogout(request, response);
                        this.sessionInformationExpiredStrategy.onExpiredSessionDetected(new SessionInformationExpiredEvent(info, request, response));
                        return;
                    }
                    //若该session存在,则刷新它的最后请求时间
                    this.sessionRegistry.refreshLastRequest(info.getSessionId());
                }
            }
            //若该session不存在,后续处理中会做未登录处理
            chain.doFilter(request, response);
        }
    

    SessionManagementFilter部分源码

        public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest)req;
            HttpServletResponse response = (HttpServletResponse)res;
            //判断是否被该过滤器处理过
            if (request.getAttribute("__spring_security_session_mgmt_filter_applied") != null) {
                chain.doFilter(request, response);
            } else {
                request.setAttribute("__spring_security_session_mgmt_filter_applied", Boolean.TRUE);
                if (!this.securityContextRepository.containsContext(request)) {
                    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                    if (authentication != null && !this.trustResolver.isAnonymous(authentication)) {
                        try {
                            this.sessionAuthenticationStrategy.onAuthentication(authentication, request, response);
                        } catch (SessionAuthenticationException var8) {
                            this.logger.debug("SessionAuthenticationStrategy rejected the authentication object", var8);
                            SecurityContextHolder.clearContext();
                            this.failureHandler.onAuthenticationFailure(request, response, var8);
                            return;
                        }
    
                        this.securityContextRepository.saveContext(SecurityContextHolder.getContext(), request, response);
                    } else if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
                        if (this.logger.isDebugEnabled()) {
                            this.logger.debug("Requested session ID " + request.getRequestedSessionId() + " is invalid.");
                        }
    
                        if (this.invalidSessionStrategy != null) {
                            this.invalidSessionStrategy.onInvalidSessionDetected(request, response);
                            return;
                        }
                    }
                }
    
                chain.doFilter(request, response);
            }
        }
    
    退出登录或删除cookie后的请求security如何处理
    • 请求中未携带 jSessionId时只能请求公共资源,无法访问私有资源。(security 定义)
      WebSecurityConfigurerAdapter继承类中定义
    @Override
    	public void configure(WebSecurity web) throws Exception {
                    //指定多个公共资源,无需登录即可访问
    		web.ignoring().antMatchers("/login.html", "/page/login/**");
    	}
    
    • 退出登录后的请求会继续验证session是否存在,不存在则重新登录。
  • 相关阅读:
    数组(Array)
    js数据类型自动转化规律
    ES6-12.Symbol
    彻底搞懂prototype和__proto__
    API测试利器——Postman(1. 安装和启动)
    全国各城市的代码邮编sql(mysql版)
    SQL执行的顺序
    jQuery $.each用法
    使用maven工具对maven项目进行打包所出现的问题
    关于Notepad++中用正则表达式匹配中文的问题
  • 原文地址:https://www.cnblogs.com/jinit/p/14148605.html
Copyright © 2011-2022 走看看