zoukankan      html  css  js  c++  java
  • Spring security学习笔记(二)

    对比两种承载认证信息的方式: session vs token

    token验证方案:

    session验证方案:

    session即会话是将用户信息保存在服务端,根据请求携带的session_id,从服务端存储(通常是redis)里提取出session。token即令牌是将用户信息保存在请求中,不过是加密后的值,在服务端需要对token进行解密,从而提取用户信息。

    浅尝JWT(JSON WEB TOKEN)

    JWT的使用场景:

    authentication: 这是JWT最常见的应用场景。当用户登陆之后,接下来的每个请求都会携带这个JWT信息。单点登录基本上使用它。
    information exchange: JWT是一种安全的多点之间信息传输的方式,因为它使用了签名。
    JWT的构成:

    • Header
    • Payload
    • Signature

    因此一个JWT看上去是长这样的:
    xxxxxx.yyyyy.zzzzzz

    在此之前,我们将用户登陆后的认证信息保存在SecurityContextHolder中,用户登陆信息保存在ThreadLocal中,理论上不能保证同一用户下一个请求是否被挡。这里将之前提到的Spring security认证方式改成使用token进行认证。

    @Slf4j
    public class PasswordAuthenticationFilter extends 	UsernamePasswordAuthenticationFilter {
    private AuthenticationManager authenticationManager;
    
    PasswordAuthenticationFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }
    
    
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {
        log.info("hello");
        try {
            AbstractAuthenticationToken authRequest = buildAuthentication(request);
            return this.authenticationManager.authenticate(authRequest);
        } catch (Exception failed) {
            throw new AuthenticationFailedException("认证失败");
        }
    }
    
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                            FilterChain chain, Authentication authResult) throws IOException, ServletException {
        response.addHeader("Authorization", "abcdefg");
    }
    
    private AbstractAuthenticationToken buildAuthentication(HttpServletRequest request) throws IOException {
        LoginInfo loginInfo = new ObjectMapper().readValue(request.getInputStream(), LoginInfo.class);
        log.info("login info is " + loginInfo);
        return new UsernameAndPasswordAuthenticationToken(loginInfo.getName(), loginInfo.getPassword());
    	}
    }
    

    这个filter extends UsernamePasswordAuthenticationFilter, 默认只对url为/login的请求进行登陆认证。

    认证成功之后,在请求头部加token信息。下次请求来的时候,会有一个TokenAuthenticationFilter对token进行验证。
    这里随意用了一个token,该token没有携带用户信息,只用来验证是否有权限访问请求。

    public class TokenAuthenticationFilter extends BasicAuthenticationFilter {
    
    public TokenAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }
    
    
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String token = request.getHeader("Authorization");
        if(!token.equals("abcdefg")) {
            filterChain.doFilter(request, response);
        } else {
            UsernameAndPasswordAuthenticationToken usernameAndPasswordAuthenticationToken =  new UsernameAndPasswordAuthenticationToken();
            usernameAndPasswordAuthenticationToken.setAuthenticated(true);
            SecurityContextHolder.getContext().setAuthentication(usernameAndPasswordAuthenticationToken);
            filterChain.doFilter(request, response);
        }
    
     	}
    }
    

    如果我们header里不带token,返回结果是403 forbidden。

    如果携带token就能成功访问请求api了。

    接下来使用JWT来创建和使用token。

    在PasswordAuthenticationFilter认证成功之后,生成一个jwt存在请求返回头里。

    在TokenAuthenticationFilter的filter流程中,首先增加jwt校验:

    然后就实现了使用jwt的方式认证。

    代码git repo: https://github.com/Rying/twitter-clone.git

    参考:
    https://blog.csdn.net/sxdtzhaoxinguo/article/details/77965226
    https://github.com/auth0/java-jwt

  • 相关阅读:
    uniapp 的组件 定义了 直接使用即可 。
    uniapp 关闭微信小程序的索引警告
    微信小程序 组件化开发 实现 导航分类文章 小程序
    微信小程序 向下滚动加载更多 和 上滑刷新的写法
    微信小程序 用 Pormise 封装 wx.request 请求
    ES6 再次学习 Promise语法(代码图解)
    Maven依赖排除及版本统一
    Maven依赖使用的范围
    SSM整合时的配置文件
    SSM整合时用到的maven依赖
  • 原文地址:https://www.cnblogs.com/holiday2000/p/9673807.html
Copyright © 2011-2022 走看看