美文网首页Spring Cloud
九、API安全机制-登录

九、API安全机制-登录

作者: 紫荆秋雪_文 | 来源:发表于2020-05-13 14:16 被阅读0次

    源码下载

    一、基于token的身份认证

    • 1、客户端(Web浏览器、APP、小程序等)调用登录服务
    • 2、登录服务通过验证后生成token,返回token给客户端同时保持token到服务端
    • 3、客户端在后续请求中携带token请求服务端
    • 4、服务端拿请求中的token来与服务端存储的token比较来判断该客户端是否已经认证
    基于token的身份认证.png

    二、基于Cookie和session的身份认证

    • 1、Web浏览器调用登录请求
    • 2、登录服务通过验证后生成一个有时效性的sessionId,同时在内存中创建一个session空间来存放sessionId的相关信息。返回一个Set-Cookie的header将sessionId存入浏览器
    • 3、客户端在后续请求中把sessionid作为请求头中的Cookie信息携带上
    • 4、服务端根据sessionid在内存中查找到相应的session来获取会话相关信息
    基于Cookie和session的实现.png

    三、Web浏览器请求

    • UserController登录请求
    @Slf4j
    @RestController
    @RequestMapping("/users")
    public class UserController {
    
        @Autowired
        private IRavenUserService userService;
    
        @GetMapping("/login")
        public void login(@Validated RavenUserInfo userInfo, HttpServletRequest request) {
            RavenUserInfo user = this.userService.login(userInfo);
            log.info(user.toString());
            // 存储到session
            request.getSession().setAttribute("user", user);
        }
    }
    
    • 登录请求需要放行
    raven:
      user:
        allowList: #需要放行的请求
          - /users/login # 登录请求
    
    • 授权过滤器
    /**
     * 请求认证过滤器
     */
    @Slf4j
    @Order(2)
    @Component
    public class AuthenticationFilter extends OncePerRequestFilter {
    
        @Autowired
        private IRavenUserService userService;
        @Autowired
        private RavenAllowsUrlConfig allowsUrlConfig;
    
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    
            logger.info("2-认证过滤器");
    
            // 直接放行
            if (this.allowsUrlConfig.getAllowList().contains(request.getRequestURI())) {
                filterChain.doFilter(request, response);
                return;
            }
    
            String header = request.getHeader("Authorization");
            if (StringUtils.isNotBlank(header)) {
                String token64 = StringUtils.substringAfter(header, "Basic ");
                String token = new String(Base64Utils.decodeFromString(token64));
                String[] items = StringUtils.splitByWholeSeparatorPreserveAllTokens(token, ":");
    
                if (items.length != 2) {
                    log.info("用户身份认证错误!!!");
                    throw new RuntimeException("用户身份认证错误!!!");
                }
                String username = items[0];
                String password = items[1];
                RavenUserInfo userInfo = this.userService.getByName(username);
                if (userInfo != null && userInfo.getPassword().equals(password)) {
                    request.getSession().setAttribute("user", userInfo);
                }
            }
            filterChain.doFilter(request, response);
        }
    }
    
    • ACL权限拦截器
    /**
     * ACL权限拦截器
     */
    @Component
    public class RavenAclInterceptor extends HandlerInterceptorAdapter {
    
        @Autowired
        private RavenAllowsUrlConfig allowsUrlConfig;
    
        /**
         * 请求前缀拦截处理
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            boolean result = true;
    
            if (this.allowsUrlConfig.getAllowList().contains(request.getRequestURI())) {
                return result;
            }
    
            // 获取用户信息
            RavenUserInfo userInfo = (RavenUserInfo) request.getSession().getAttribute("user");
    
            if (null == userInfo) {
                // 用户未认证
                response.setContentType("text/plain");
                response.getWriter().write("need authentication");
                response.setStatus(HttpStatus.UNAUTHORIZED.value());
                result = false;
            }
            else {
                // 用户没有权限
                String method = request.getMethod();
                if (!userInfo.hasPermission(method)) {
                    response.setContentType("text/plain");
                    response.getWriter().write("forbidden");
                    response.setStatus(HttpStatus.FORBIDDEN.value());
                    result = false;
                }
            }
            return result;
        }
    }
    
    • 为了防止session攻击,确保每次登录都生成新的session
        @GetMapping("/login")
        public void login(@Validated RavenUserInfo userInfo, HttpServletRequest request) {
            RavenUserInfo user = this.userService.login(userInfo);
            log.info(user.toString());
            HttpSession session = request.getSession(false);
            if (session != null) {
                // 把已存在的session过期
                session.invalidate();
            }
            // 保证每一次登录都是一个新的session
            request.getSession(true).setAttribute("user", user);
        }
    

    相关文章

      网友评论

        本文标题:九、API安全机制-登录

        本文链接:https://www.haomeiwen.com/subject/xuwgnhtx.html