Simple JWT

The reason why JWT can be used as a standard for declaration transmission is that it has its own structure, which is not just to issue a token casually. The structure of JWT for token generation has three parts. Separated.

  • HeaderThe header contains two main parts,tokenType and encryption algorithm, such as{typ: "jwt", alg: "HS256"}.HS256Is refers tosha256The algorithm will convert this object tobase64.
  • PayloadThe payload is where the valid information is stored, and the valid information is divided into declarations registered in the standard, public declarations, and private declarations.
  • SignatureThis part is going to beHeaderPayloadThrough the keysecretAnd the salting algorithm,secretThe key is stored on the server and never sent to anyone, so JWT’s transmission is secure.
  1. Configuration of pom

    <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
     </dependency>
    Copy the code
  2. JWTUtils

      private static long time = 1000*60; // Expiration time
        private  static String signtrue = "@@wzj##hahahha"; / / add salt
    
        / / create a token
        public static String createToken(User user){
            JwtBuilder jwtBuilder = Jwts.builder();
    
            String token = jwtBuilder
                    .setHeaderParam("typ"."JWT")// The header can be left blank
                    .setHeaderParam("alg"."HS256")
                    .claim("userId"."user.getId()")/ / data
                    .claim("username",user.getUsername()) 
                    .setExpiration(new Date(System.currentTimeMillis()+time))/ / the period of validity
                    .signWith(SignatureAlgorithm.HS256,signtrue)/ / encryption
                    .compact();/ / synthetic token
            System.out.println(token);
            return token;
        }
        / / check the token
        public static boolean checkToken(String token){
            if(token == null) {return false;
            }
            try {
                Jws<Claims> claimsJws = Jwts.parser().setSigningKey(signtrue).parseClaimsJws(token);// If the token is not valid, it is invalid
            } catch (Exception e) {
                return false;
            }
            return true; }}Copy the code
  3. Create an interceptor that blocks requests with tokens to access them. Here the simple JWT I will just verify that the token exists to try.

    @Component
    public class JWTInterceptor implements HandlerInterceptor {
        
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
            String token = request.getHeader("token");
            if(JwtUtils.checkToken(token)){
                return  true;
            }else{
                System.out.println("Not logged in");
                return false; }}@Override
        public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView)  {}@Override
        public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e)  {}}Copy the code
  4. Create WebConfiguration to add the interceptor. If swagger is used, all paths of Swagger must be excluded.

    @Configuration
    public class WebConfiguration implements WebMvcConfigurer {
    
        / / swagger path
        String[] swaggerExcludes=new String[]{"/swagger-resources/**"."/webjars/**"."/v2/**"."/swagger-ui/**"};
    
        @Bean
        JWTInterceptor jwtInterceptor(a){
            return new JWTInterceptor();
        }
        // Spring interceptors are loaded before springcontentText, so @bean is loaded ahead of time. Otherwise, the @AutoWired injection in the filter will be null
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(jwtInterceptor()).addPathPatterns("/ * *")// Intercept all
                    .excludePathPatterns(Arrays.asList("/"."/login"."/blogs"))// The path to exclude
                    .excludePathPatterns(swaggerExcludes);/ / exclude swagger}}Copy the code
  5. test

JWT increase redis

I am watching crazy god said redis tutorial, can say I a lot of tutorials a lot of are here to see, is worth paying attention to learning up Lord crazy god said Redis can first see 1-13 and 25, 26, 27 sets in his words, so that is to do the first %90 API call programmers. I used the crazy God encapsulation class ReidsUtil and configured custom annotations that can be obtained by watching the video on the public account. I hope you will learn better and better.

  1. Login business layer code changed

    That is, the generated token is put in redis. I regard the token as the key here and save the use image. Because I thought it would give me a better idea of who the current logged-in user is.

     public Result findByUsername(String username, String password) {
            User user = userMapper.findByUsername(username,password);
            if(user ! =null) {
                /***************** Changed code *******************/
                String token = JwtUtils.createToken(user);
                redisUtil.set("token"+token,user,60*5);
                / * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
                return Result.success(token);
            }else{
                // This is not a good idea
                return Result.fail("error"); }}Copy the code
  2. JWT interceptor changes

    Very simple is to take the current key token to redis to find the current login user, if not empty or correct. I added a thread to hold the user.

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
            if(! (handlerinstanceof HandlerMethod)){
                A Springboot program that accesses static resources goes to the static directory of the classpath by default
                return true;
            }
            String token = request.getHeader("token");
            / / * * * * * * * * * * * * * * * * * * * /
            User user = (User)redisUtil.get("token"+token);
            if(user ! =null){
                UserTheadLocal.put(user) ;
             / / * * * * * * * * * * * * * * * * * * * * * * * * * * * * / /
                return  true;
            }else{
                Result result = Result.fail("Not logged in");
                response.setContentType("application/json; charset=utf-8");
                response.getWriter().print(JSON.toJSONString(result));
                return false; }}Copy the code
  3. UserTheadLocal thread

    Increased efficiency in adding articles and other situations where current user information is needed. It is safer to take advantage of thread isolation.

    public class UserTheadLocal {
    
        private UserTheadLocal(a){};
        // Thread isolation
        private static  final  ThreadLocal<User> LOCAL = new ThreadLocal<>();
    
        public static  void put(User user){
            LOCAL.set(user);
        }
    
        public  static  User get(a){
            return  LOCAL.get();
        }
    
        public static  void remove(a){ LOCAL.remove(); }}Copy the code

Redis is used in other businesses

  1. Home page has query all articles, here do not want to put in Redis certainly improve efficiency

     public Result findAllBlogs(Integer currentPage) {
            Page pageMap = (Page) redisUtil.get("pageMap");
            if (pageMap == null) {
                System.out.println("********** go database **************");
                Page page = new Page(currentPage, 5);
                QueryWrapper<Blog> query = new QueryWrapper<Blog>();
                pageMap = blogMapper.selectMapsPage(page, query.orderByDesc("created"));
                String pageList = JSON.toJSONString(pageMap);
                redisUtil.set("pageMap", pageMap, 60 * 5);
            } else {
                System.out.println("* * * * * * * * * * * go Redis * * * * * * * * * * * *");
            }
            return Result.success(pageMap);
        }
    Copy the code
  2. Redis is also added to query individual articles, but the redia duration can be shorter

    I made an error here, using fastJson from the database that json data can not directly encapsulate the object,

    So we used parseObject to deserialize.

    public Blog selectBlog(Long id) {
            String blogJson1 = (String)redisUtil.get("Blog" + id);
            Blog blog = JSON.parseObject(blogJson1,Blog.class);
            if (blog == null) {
                System.out.println("********** go database **************");
                blog = blogMapper.selectById(id);
                String blogJson = JSON.toJSONString(blog);
                System.out.println(blogJson);
                redisUtil.set("Blog" + id, blogJson, 60 * 2);
            }else{
                System.out.println("* * * * * * * * * * * go Redis * * * * * * * * * * * *");
            }
            return blog;
        }
    Copy the code

Solve the puzzles in Canto ii

Here, I added the add interface. At that time, IT was probably too ** * and I didn’t think of it.

  1. BlogVo receives some information about blogs

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class BlogVo {
    
        private Long id;
    
        @notblank (message = "title cannot be empty ")
        private String title;
    
        @notblank (message = "Digest cannot be empty ")
        private String description;
    
        @notblank (message = "content cannot be empty ")
        private String content;
    }
    
    Copy the code
  2. /add Adds the article

        @apiOperation (value = "add article ")
        @PostMapping("/blog/add")
        public Result add( @RequestBody BlogVo blogVo){
            System.out.println(blogVo);
            Blog blog = new Blog();
            blog.setCreated(LocalDateTime.now());
            blog.setUserId(UserTheadLocal.get().getId());
            blog.setStatus(0);
    // BeanUtils.copyProperties(blog, blogVo); I can't use it here
            blog.setContent(blogVo.getContent());
            blog.setDescription(blogVo.getDescription());
            blog.setTitle(blogVo.getTitle());
            System.out.println(blog);
            boolean edit = blogService.insertBlog(blog);
            if(edit){
                return Result.success(200."Added successfully".null);
            }
            return Result.fail("Add failed");
        }
    Copy the code
  3. /edit Modifies the article

     @apiOperation (value = "ApiOperation ")
        @PostMapping("/blog/edit")
        public Result edit(@Validated @RequestBody BlogVo blogVo){
            Blog temp = null;
            temp = blogService.selectBlog(blogVo.getId());
            if(temp ! =null) {if(UserTheadLocal.get().getId() ! = temp.getUserId()){return Result.fail("No permission to modify");
                }else{
    // BeanUtils.copyProperties(temp,blogVo);
                    temp.setContent(blogVo.getContent());
                    temp.setDescription(blogVo.getDescription());
                    temp.setTitle(blogVo.getTitle());
                    boolean flag  = blogService.updateBlog(temp);
                    if(flag){
                        return Result.success(200."Modified successfully".null);
                    }else{
                        return  Result.fail("Modification failed"); }}}return  Result.fail("Modification failed");
        }
    Copy the code

conclusion

JWT is not difficult. In the future, we should not be fooled by strange technical words we hear. If it is a technology, we can learn and master it if they dare to speak out.

Redis, I’m just scratching the surface, oriented towards API calls. I like crazy god very much, because his video has a lot of chicken soup, this thing may be useless to some people, but I seem to be very emotional ah, watching other videos I will be sleepy, watching his video chicken soup to feed me blood boiling. Redis still has to master it.

Problematic connection

QQ 1819220754