zoukankan      html  css  js  c++  java
  • Spring Boot使用JWT实现系统登录验证

    简介

    什么是JWT(Json Web Token)

    jwt是为了在网络应用环境间传递声明而执行的一种基于json的开放标准。该token被设计紧凑且安全的,特别适用于SSO场景。
    jwt的声明一般被用来在身份提供者和服务提供者之间传递被认证的用户身份信息。

    JWT长什么样

    eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0MDAyIiwiZXhwIjoxNTEwOTcwMjU4fQ._FOqy5l44hODu3DjXh762LNUTLNQH15fdCUerdseDpmSKgkVSCjOyxQNTBKDSh3N-c83_pdEw5t6BdorgRU_kw

    JWT的构成

    JWT通常由三部分组成,头信息(header)、消息体(body)、签名(signature)
    头信息指定了JWT使用的签名算法

    header={alg=HS512}

    消息体包含了JWT的意图,exp为令牌过期时间

    body={sub=testUsername, exp=1510886546}

    签名通过私钥生成

    signature=kwq8a_B6WMqHOrEi-gFR5rRPmPL7qoShZJn0VFfXpXc1Yfw6BfVrliAP9C4UnXlqD3wRXO3mw_DDIdglN5lH9Q

    使用springboot集成jwt

    jwt官网

    springboot官网

    引用依赖

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
    
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-security</artifactId>
      </dependency>
    
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-actuator</artifactId>
      </dependency>
    
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-devtools</artifactId>
      </dependency>
    
      <dependency>
          <groupId>io.jsonwebtoken</groupId>
          <artifactId>jjwt</artifactId>
          <version>0.7.0</version>
      </dependency>

    构建普通rest接口

      @RestController
      @RequestMapping("/employee")
      public class EmployeeController {
    
          @GetMapping("/greeting")
           public String greeting() {
               return "Hello,World!";
           }
       }

    JwtLoginFilter

    public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {
    
       private AuthenticationManager authenticationManager;
    
       public JwtLoginFilter(AuthenticationManager authenticationManager) {
           this.authenticationManager = authenticationManager;
       }
    
      @Override
      public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {
          Employee employee = new Employee();
           return authenticationManager.authenticate(
                   new UsernamePasswordAuthenticationToken(
                       employee.getUsername(),
                       employee.getPassword(),
                       new ArrayList<>()
                  )
           );
       }
    
      @Override
      protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, 
       FilterChain chain, Authentication authResult) throws IOException, ServletException {
          String token = Jwts.builder()
               .setSubject(((User) authResult.getPrincipal()).getUsername())
               .setExpiration(new Date(System.currentTimeMillis() + 30 * 60 * 1000))
               .signWith(SignatureAlgorithm.HS512, "JWTSecret")
               .compact();
    
           response.addHeader("Authorization", JwtUtils.getTokenHeader(token));
      }

    }

    JwtAuthenticationFilter

      public class JwtAuthenticationFilter extends BasicAuthenticationFilter {
    
      public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
          super(authenticationManager);
      }
    
      @Override
      protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
          String header = request.getHeader("Authorization");
    
          if (header == null || !header.startsWith(JwtUtils.getAuthorizationHeaderPrefix())) {
              chain.doFilter(request, response);
             return;
          }
    
          UsernamePasswordAuthenticationToken authenticationToken = getUsernamePasswordAuthenticationToken(header);
    
          SecurityContextHolder.getContext().setAuthentication(authenticationToken);
          chain.doFilter(request, response);
      }
    
      private UsernamePasswordAuthenticationToken getUsernamePasswordAuthenticationToken(String token) {
          String user = Jwts.parser()
                  .setSigningKey("PrivateSecret")
                  .parseClaimsJws(token.replace(JwtUtils.getAuthorizationHeaderPrefix(), ""))
                  .getBody()
                  .getSubject();
    
          if (null != user) {
              return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
          }
    
          return null;
      }
      }

    SecurityConfiguration

      @Configuration
      @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
      public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    
    
        @Override
        public void configure(WebSecurity web) throws Exception {
              super.configure(web);
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
          http.cors().and().csrf().disable().authorizeRequests()
                  .anyRequest().authenticated()
                  .and()
                  .addFilter(new JwtLoginFilter(authenticationManager()))
                  .addFilter(new JwtAuthenticationFilter(authenticationManager()));
        }
    
      }

    使用postman测试

    首先我们先测试/employee/greeting 响应如下:

    {
    "timestamp": 1510887634904,
    "status": 403,
    "error": "Forbidden",
    "message": "Access Denied",
    "path": "/employee/greeting"
    }

    很明显,状态码为403,此刻我们如果先登录拿到token后再测试呢,测试如下

    postman-test1

    登录成功后,我们可以看到headers中已经带有jwt

    authorization →Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0VXNlcm5hbWUiLCJleHAiOjE1MTA4ODkxMDd9.FtdEM0p84ff5CzDcoiQhtm1MF_NfDH2Ij1jspxlTQhuCISIzYdoU40OsFoxam9F1EXeVw2GZdQmArVwMk6HO1A

    由于postman在一般情况下不支持自定义header 这个时候我们需要下载一个插件开启interceptor 开启后将authorization 放入header继续测试:
    postman-test3

    postman-test2

    这时我们发现已经成功返回hello,world!

    最后附上代码GitHub地址:源码下载

    本文转载自

    原文作者:胡运凡

    原文链接:https://www.cnblogs.com/huyunfan/p/7850680.html

     
  • 相关阅读:
    有关 JavaScript 的 10 件让人费解的事情
    Apache ab介绍1
    Oracle Raw,number,varchar2... 转换
    Flex开发者需要知道的10件事
    linux命令之nice
    JavaIO复习和目录文件的复制
    使用php获取网页内容
    linux 安装sysstat使用iostat、mpstat、sar、sa
    SQL Injection 实战某基金
    ubuntu root锁屏工具
  • 原文地址:https://www.cnblogs.com/xifengxiaoma/p/9508477.html
Copyright © 2011-2022 走看看