乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      json-web-token(JWT)

       貪挽懶月 2022-06-20 發(fā)布于廣東
      JWT是什么


      JWT的全稱為json web token。不要把它想得多么高深,其實(shí)就是一種生成token的方式。一般我們?cè)L問一個(gè)系統(tǒng)的流程就是:請(qǐng)求登錄接口,該接口會(huì)返回一個(gè)token,請(qǐng)求其他接口都要帶上token,token驗(yàn)證通過才能訪問成功,而JWT可以理解為就是生成token的一種機(jī)制。

      JWT怎么用

      1、添加jwt的依賴:

      <!-- JWT -->
      <dependency>
          <groupId>com.auth0</groupId>
          <artifactId>java-jwt</artifactId>
          <version>3.4.0</version>
      </dependency>

      2、新建一個(gè)TokenService,用來生成token:

      @Service
      public class TokenService {
          // token過期時(shí)間5分鐘
          private static final long EXPIRE_TIME = (60 * 1000 * 5);

          public String getToken(User user) {
              return JWT.create()
                      // 需要放入token中的信息
                      .withAudience(user.getId())
                      // 設(shè)置token過期時(shí)間
                      .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRE_TIME))
                      // 用戶密碼當(dāng)作密鑰
                      .sign(Algorithm.HMAC256(user.getPassword()));
          }
      }

      User類就是一個(gè)普通的pojo,這里就不把代碼貼出來了。這個(gè)getToken方法表示將用戶的密碼作為密鑰,把用戶的id放進(jìn)token中,設(shè)置token過期時(shí)間為5分鐘。

      3、新建兩個(gè)注解,一個(gè)注解表示需要驗(yàn)證,另一個(gè)表示跳過驗(yàn)證:

      • 需要驗(yàn)證:

      //可以作用在方法,類和接口上
      @Target({ElementType.METHOD, ElementType.TYPE})
      //編譯器會(huì)將SkipToken的信息保存在虛擬機(jī)中
      @Retention(RetentionPolicy.RUNTIME)
      public @interface NeedToken {
          // required 屬性默認(rèn)值為true
          boolean required() default true;
      }
      • 跳過驗(yàn)證:

      @Target({ElementType.METHODElementType.TYPE})
      @Retention(RetentionPolicy.RUNTIME)
      public @interface SkipToken {
          boolean required() default true;
      }

      4、新建一個(gè)AuthInterceptor類,用于攔截請(qǐng)求:

      public class AuthInterceptor implements HandlerInterceptor {
          @Autowired
          private UserService userService;

          @Override
          public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,Object object) {
              // 從 http 請(qǐng)求頭中取出 token
              String token = httpServletRequest.getHeader("token");
              // 只攔截方法,不是方法直接返回true
              if (!(object instanceof HandlerMethod)) {
                  return true;
              }
              HandlerMethod handlerMethod = (HandlerMethod) object;
              Method method = handlerMethod.getMethod();
              // 有SkipToken注解的直接跳過認(rèn)證
              if (method.isAnnotationPresent(SkipToken.class)) {
                  SkipToken skipToken = method.getAnnotation(SkipToken.class);
                  if (skipToken.required()) {
                      return true;
                  }
              }
              // 有NeedToken注解的就進(jìn)行認(rèn)證
              if (method.isAnnotationPresent(NeedToken.class)) {
                  NeedToken needToken = method.getAnnotation(NeedToken.class);
                  if (needToken.required()) {
                      if (token == null) {
                          throw new RuntimeException("無token,請(qǐng)重新登錄");
                      }
                      // 獲取 token 中的 userId
                      String userId;
                      try {
                          userId = JWT.decode(token).getAudience().get(0);
                      } catch (JWTDecodeException j) {
                          throw new RuntimeException("401");
                      }
                      // 根據(jù)userId查詢數(shù)據(jù)庫(kù)
                      User user = userService.findUserById(userId);
                      if (user == null) {
                          throw new RuntimeException("用戶不存在,請(qǐng)重新登錄");
                      }
                      // 用查出來的user的密碼去校驗(yàn)token
                      JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
                      try {
                          // 沒發(fā)生異常就表示校驗(yàn)通過
                          jwtVerifier.verify(token);
                      } catch (JWTVerificationException e) {
                          throw new RuntimeException("401");
                      }
                      return true;
                  }
              }
              return true;
          }

          @Override
          public void postHandle(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse, Object o,ModelAndView modelAndView) {
          }

          @Override
          public void afterCompletion(HttpServletRequest httpServletRequest,HttpServletResponse httpServletResponse,Object o, Exception e) {
          }
      }

      這個(gè)攔截器的處理邏輯就是:

      • 只攔截方法,如果不是方法,就放行;

      • 如果攔截的方法有@SkipToken注解,放行;

      • 如果攔截的方法有@NeedToken注解,則需要驗(yàn)證token;

      • 取出請(qǐng)求頭中的token,拿出token中的userId,根據(jù)此userId去數(shù)據(jù)庫(kù)查詢對(duì)應(yīng)的記錄;

      • 再將查出來的user的password去驗(yàn)證token,驗(yàn)證成功則放行;

      • 如果沒有@NeedToken也沒有@SkipToken注解的,也放行。

      5、新建一個(gè)InterceptorConfig類,將我們上面寫的攔截器配置到spring容器中去:

      @Configuration
      public class InterceptorConfig implements WebMvcConfigurer {
          @Override
          public void addInterceptors(InterceptorRegistry registry) {
              registry.addInterceptor(authInterceptor())
                      .addPathPatterns("/**");   
          }
          @Bean
          public AuthInterceptor authInterceptor() {
              return new AuthInterceptor();
          }
      }

      6、在controller中的用法:

      @RestController
      @RequestMapping("api")
      public class UserController {
          @Autowired
          private UserService userService;
          @Autowired
          private TokenService tokenService;

          @SkipToken
          @PostMapping("/user")
          public JsonResult login(User user){
              User dbUser = userService.findForLogin(user);
              if (dbUser == null){
                  return new JsonResult(200"用戶名或密碼錯(cuò)誤"null);
              } else {
                  String token = tokenService.getToken(dbUser);
                  Map<String, Object> resultMap = new HashMap<>();
                  resultMap.put("token", token);
                  resultMap.put("user", dbUser);
                  return new JsonResult(200"登錄成功", resultMap);
              }
          }

          @NeedToken
          @GetMapping("/getMessage")
          public String getMessage(){
              return "你已通過驗(yàn)證";
          }

          @SkipToken
          @GetMapping("/noToken")
          public String noToken() {
              return "無需token訪問";
          }
      }

      以上就是JWT的用法,其實(shí)在實(shí)際生產(chǎn)中一般會(huì)配合shiro使用。

      -java開發(fā)那些事兒-

        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多