SpringBoot整合JWT

SpringBoot整合JWT

概述

有关jwt的的详细概述请参考阮一峰博客入门教程:https://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html

整合

导包–采用 java-jwt jar包

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

<!--Hutool Java工具包-->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.4.0</version>
</dependency>

编写jwt工具类

/**
 * jwt工具类
 *
 * @Author nanfeng
 */

@Slf4j
public class JwtTokenUtil {

    private final static Long expiration = 72000000L;

    private final static String tokenHeader = "Authorization";

    private final static String secret = "secret";



    /**
     * 校验 token是否正确
     *
     * @param token  密钥
     * @return 是否正确
     */
    public static boolean verify(String token, String username) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withClaim("username", username)
                    .build();
            verifier.verify(token);
            log.info("token is valid");
            return true;
        } catch (TokenExpiredException e) {
            throw new BaseException(HttpStatus.HTTP_UNAUTHORIZED,"登录过期,请重新登录");
        } catch (Exception e) {
            log.info("token is invalid {}", e.getMessage());
            throw new BaseException(e.getMessage());
        }
    }

    /**
     * 从 token中获取用户名
     *
     * @return token中包含的用户名
     */
    public static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("username").asString();
        } catch (JWTDecodeException e) {
            log.error("error:{}", e.getMessage());
            throw new JWTDecodeException(e.getMessage());
        }
    }

    /**
     * 生成 token
     *
     * @param username 用户名
     * @return token
     */
    public static String sign(String username) {

        try {
            username = StringUtils.lowerCase(username);
            Date date = new Date(System.currentTimeMillis() + expiration * 1000);
            Algorithm algorithm = Algorithm.HMAC256(secret);
            return JWT.create()
                    .withClaim("username", username)
                    .withExpiresAt(date)
                    .sign(algorithm);

        } catch (Exception e) {
            log.error("error:{}", e);
            throw new BaseException(e.getMessage());
        }

    }


    /**
     * 获取请求token
     *
     * @param request
     * @return token
     */
    public static String getToken(HttpServletRequest request) {
        String requestHeader = request.getHeader(tokenHeader);
        String token = null;
        if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
            token = requestHeader.substring(7);
        }
        return token;
    }

}

token拦截器

/**
 * jwt 过滤器
 *
 * @Author nanfeng
 */
@Component
public class TokenInterceptor implements HandlerInterceptor {

    @Autowired
    private UserService userService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {

        // 跨域时会首先发送一个 option请求,这里我们给 option请求直接返回正常状态
        if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
            response.setStatus(HttpStatus.HTTP_OK);
            return true;
        }
        response.setCharacterEncoding("utf-8");
        String username = null;
        String authToken = JwtTokenUtil.getToken(request);

        if (StrUtil.isNotBlank(authToken)) {
            username = JwtTokenUtil.getUsername(authToken);

        }
        if (StrUtil.isNotBlank(username)) {
            User user = userService.findByName(username);
            if (JwtTokenUtil.verify(authToken, user.getUsername())) {
                return true;
            }
        }

        return false;
    }
}

配置不需验证的请求

/**
 * 请求拦截器,配置不拦截请求
 *
 * @Author nanfeng
 * @Date 2021/4/7 15:26
 */
@Configuration
public class WebConfigurer implements WebMvcConfigurer {

    @Autowired
    private TokenInterceptor tokenInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(tokenInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/login")
                .excludePathPatterns("/doc.html/**","/swagger-resources/**", "/webjars/**", "/v2/**");
    }
}

编写登录接口

@RestController
@Api(tags = "登录接口")
public class LoginController {

    @Autowired
    private LoginService loginService;

    @PostMapping(value = "/login")
    @ApiOperation(value = "登录",notes = "username,password,code")
    public AjaxResult login(@RequestBody LoginBody loginBody){
        Map<String, Object> map = new AjaxResult();
        String token = loginService.verify(loginBody);

        map.put("token", token);

        return AjaxResult.success(map);
    }

}

登录验证

@Component
@Slf4j
public class LoginService {

    @Autowired
    private UserService userService;

    public String verify(LoginBody loginBody) {

        String encryptPassword = DigestUtil.md5Hex(loginBody.getPassword());
        User user = userService.findByName(loginBody.getUsername());
        if (ObjectUtil.isNull(user)) {
            throw new BaseException("该用户名不存在");
        } else {
            if (!StrUtil.equals(user.getPassword(), encryptPassword)) {
                throw new BaseException(HttpStatus.HTTP_UNAUTHORIZED, "用户名或密码错误");
            }
            return JwtTokenUtil.sign(loginBody.getUsername());
        }

    }

}

整合过程用到的统一结果输出

public class AjaxResult extends HashMap<String, Object>
{
    private static final long serialVersionUID = 1L;

    /** 状态码 */
    public static final String CODE_TAG = "code";

    /** 返回内容 */
    public static final String MSG_TAG = "msg";

    /** 数据对象 */
    public static final String DATA_TAG = "data";
    /** 数量长度 */
    public static final String TOTAL_TAG = "total";
    /**
     * 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。
     */
    public AjaxResult()
    {
    }

    /**
     * 初始化一个新创建的 AjaxResult 对象
     *
     * @param code 状态码
     * @param msg 返回内容
     */
    public AjaxResult(int code, String msg)
    {
        super.put(CODE_TAG, code);
        super.put(MSG_TAG, msg);
    }

    /**
     * 初始化一个新创建的 AjaxResult 对象
     *
     * @param code 状态码
     * @param msg 返回内容
     * @param data 数据对象
     */
    public AjaxResult(int code, String msg, Object data)
    {
        super.put(CODE_TAG, code);
        super.put(MSG_TAG, msg);
        if (ObjectUtil.isNotNull(data))
        {
            super.put(DATA_TAG, data);
        }
    }

    public AjaxResult(int code, String msg, Long total, Object data)
    {
        super.put(CODE_TAG, code);
        super.put(MSG_TAG, msg);
        super.put(TOTAL_TAG,total);
        if (ObjectUtil.isNotNull(data))
        {
            super.put(DATA_TAG, data);
        }
    }

    /**
     * 返回成功消息
     *
     * @return 成功消息
     */
    public static AjaxResult success()
    {
        return AjaxResult.success("操作成功");
    }

    /**
     * 返回成功数据
     *
     * @return 成功消息
     */
    public static AjaxResult success(Object data)
    {
        return AjaxResult.success("操作成功", data);
    }

    /**
     * 分页查询返回
     * @param total
     * @param data
     * @return
     */
    public static AjaxResult success(Long total,Object data){
        return AjaxResult.totalSuccess("操作成功",total,data);
    }
    /**
     * 返回成功消息
     *
     * @param msg 返回内容
     * @return 成功消息
     */
    public static AjaxResult success(String msg)
    {
        return AjaxResult.success(msg, null);
    }

    /**
     * 返回成功消息
     *
     * @param msg 返回内容
     * @param data 数据对象
     * @return 成功消息
     */
    public static AjaxResult success(String msg, Object data)
    {
        return new AjaxResult(HttpStatus.HTTP_OK, msg, data);
    }

    /**
     * 返回分页成功消息
     * @param msg
     * @param total
     * @param data
     * @return
     */
    public static AjaxResult totalSuccess(String msg,Long total,Object data)
    {
        return new AjaxResult(HttpStatus.HTTP_OK, msg,total,data);
    }

    /**
     * 返回错误消息
     *
     * @return
     */
    public static AjaxResult error()
    {
        return AjaxResult.error("操作失败");
    }

    /**
     * 返回错误消息
     *
     * @param msg 返回内容
     * @return 警告消息
     */
    public static AjaxResult error(String msg)
    {
        return AjaxResult.error(msg, null);
    }

    /**
     * 返回错误消息
     *
     * @param msg 返回内容
     * @param data 数据对象
     * @return 警告消息
     */
    public static AjaxResult error(String msg, Object data)
    {
        return new AjaxResult(HttpStatus.HTTP_INTERNAL_ERROR, msg, data);
    }

    /**
     * 返回错误消息
     *
     * @param code 状态码
     * @param msg 返回内容
     * @return 警告消息
     */
    public static AjaxResult error(int code, String msg)
    {
        return new AjaxResult(code, msg, null);
    }
}

 结果

 {
	 "msg": "操作成功",
	 "code": 200,
	 "data": {
	 		"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.xxx.neWhVBM0Vx9hBHYPjyS3dXoJ0rhdpwOUofsGZA3URrA"
		}
  }
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nan feng

打赏一杯咖啡吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值