spring boot项目集成jwt实现权限控制

前面一篇介绍了springboot同时集成shiro和jwt实现的登录检验,权限控制功能,但是我们有时候仅仅需要进行一个登录校验而不需要权限的控制,那么我们就只需要集成jwt即可。

一、编写用户实体类

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;

}

二、jwt工具类:生成token和校验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();
    }
}

三、JwtFilter 实现Filter接口

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() {
    }
}

四、 JwtConfig 如果不使用注解式注册过滤器,则可以使用代码注册方式注册过滤器

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;
    }
}


五、编写测试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失败");
        }
    }

}

请求接口,会生成一个token字符串,我们需要在请求其他的接口的时候,在请求头设置 

authorization = 生成的token

猜你喜欢

转载自blog.csdn.net/qq_31905135/article/details/108826096