Spring boot project integrates jwt to achieve permission control

The previous article introduced the login verification and permission control functions implemented by springboot integrating shiro and jwt at the same time, but sometimes we only need to perform a login verification without permission control, then we only need to integrate jwt.

One, write user entity class

package com.sf.gis.boot.rcboot.jwt;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

/**
 * @author 80004819
 * @ClassName:
 * @Description:
 * @date 2020年09月11日 17:27:58
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class User {

    private String userName;

    private String password;

}

Two, jwt tools: generate token and verify token

package com.sf.gis.boot.rcboot.jwt;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 80004819
 * @ClassName:
 * @Description:
 * @date 2020年09月11日 17:26:55
 */
@Slf4j
public class JwtUtil {
    /**
     * 密钥
     */
    private static final String SECRET = "my_secret";

    /**
     * 过期时间
     **/
    private static final long EXPIRATION = 1800L;//单位为秒

    /**
     * 生成用户token,设置token超时时间
     */
    public static String createToken(User user) {
        //过期时间
        Date expireDate = new Date(System.currentTimeMillis() + EXPIRATION * 1000);
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");
        String token = JWT.create()
                .withHeader(map)// 添加头部
                //可以将基本信息放到claims中
                .withClaim("userName", user.getUserName())//userId
                .withClaim("password", user.getUserName())//userName
                .withExpiresAt(expireDate) //超时设置,设置过期的日期
                .withIssuedAt(new Date()) //签发时间
                .sign(Algorithm.HMAC256(SECRET)); //SECRET加密
        return token;
    }

    /**
     * 校验token并解析token
     */
    public static Map<String, Claim> verifyToken(String token) {
        DecodedJWT jwt = null;
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
            jwt = verifier.verify(token);
        } catch (Exception e) {
            log.error(e.getMessage());
            log.error("token解码异常");
            //解码异常则抛出异常
            return null;
        }
        return jwt.getClaims();
    }
}

Three, JwtFilter implements the Filter interface

package com.sf.gis.boot.rcboot.jwt;

import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.interfaces.Claim;
import com.google.gson.Gson;
import com.sf.gis.boot.rcboot.util.JsonResponse;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * @author 80004819
 * @ClassName:
 * @Description:
 * @date 2020年09月11日 17:34:49
 */
@Slf4j
//直接使用注解方式注册过滤器,需要在启动类上添加@ServletComponentScan注解
//@WebFilter(filterName = "JwtFilter", urlPatterns = "/*")
public class JwtFilter implements Filter {

    private static final Gson GSON = new Gson();


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        final HttpServletRequest request = (HttpServletRequest) req;
        final HttpServletResponse response = (HttpServletResponse) res;

        //设置编码格式
        response.setContentType("text/html;charset=utf-8");
        response.setCharacterEncoding("UTF-8");

        //获取 header里的token
        final String token = request.getHeader("authorization");

        if ("OPTIONS".equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
            chain.doFilter(request, response);
        }
        // Except OPTIONS, other request should be checked by JWT
        else {

            String requestURI = request.getRequestURI();
            if (isPass(requestURI)) {
                chain.doFilter(req, res);
                return;
            }

            if (token == null) {
                response.getWriter().write(GSON.toJson(JsonResponse.error("没有token")));
                return;
            }
            //如果获取到了token,验证token是否合法
            Map<String, Claim> userData = JwtUtil.verifyToken(token);
            if (userData == null) {
                response.getWriter().write(GSON.toJson(JsonResponse.error("token不合法!")));
                return;
            }
            String userName = userData.get("userName").asString();
            String password = userData.get("password").asString();
            //拦截器 拿到用户信息,放到request中
//            request.setAttribute("userName", userName);
//            request.setAttribute("password", password);
            chain.doFilter(req, res);
        }
    }

    /**
     * 直接通行的uri
     *
     * @param requestURI
     * @return
     */
    private boolean isPass(String requestURI) {
        return StrUtil.equals(requestURI, "/") || StrUtil.startWithIgnoreCase(requestURI, "/jwt/getToken") ||
                StrUtil.startWithIgnoreCase(requestURI, "/swagger-ui.html") ||
                StrUtil.startWithIgnoreCase(requestURI, "/error")
                || StrUtil.startWithIgnoreCase(requestURI, "/csrf")
                || StrUtil.containsAnyIgnoreCase(requestURI, "v2/api-docs", "swagger");
    }

    @Override
    public void destroy() {
    }
}

Four, JwtConfig If you do not use annotation type registration filter, you can use the code registration method to register the filter

package com.sf.gis.boot.rcboot.jwt;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author 80004819
 * @ClassName:
 * @Description:
 * @date 2020年09月11日 17:47:32
 */
@Configuration
public class JwtConfig {

    @Bean
    public FilterRegistrationBean filterRegistrationBean (){

        FilterRegistrationBean filterRegistrationBean=  new FilterRegistrationBean();
        JwtFilter jwtFilter = new JwtFilter();
        filterRegistrationBean.setFilter(jwtFilter);
        filterRegistrationBean.addUrlPatterns("/*");
        return filterRegistrationBean;
    }
}


Five, write test controller

package com.sf.gis.boot.rcboot.controller;

import com.sf.gis.boot.rcboot.shiro.JWTUtil;
import com.sf.gis.boot.rcboot.util.JsonResponse;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author 80004819
 * @ClassName:
 * @Description:
 * @date 2020年09月11日 17:38:09
 */
@RestController
@RequestMapping("/jwt")
@Slf4j
@Api(tags = "JWT权限controller")
public class JwtTokenController {


    /**
     * 模拟登陆接口获取到token,有效期为30分钟
     *
     * @return
     */
    @GetMapping("/getToken")
    public JsonResponse getToken() {
        try {
            //String token = JWTUtil.createToken(new User("admin", "123456"));
            String token = JWTUtil.sign("admin", "123456", false);
            return JsonResponse.ok(JsonResponse.STATUS_SUCCESS, token);
        } catch (Exception e) {
            log.error("error", e);
            return JsonResponse.error("获取token失败");
        }
    }

}

Request interface, will generate a token string, we need to set in the request header when requesting other interfaces 

authorization = generated token

 

Guess you like

Origin blog.csdn.net/qq_31905135/article/details/108826096