Springboot使用JWT做用户权限区分

** 简介:**对除了登录注册之外的接口做访问拦截,登录之后传递token值,之后每次前端访问接口都携带token,并在后端做一个公共类可以获取当前访问的用户信息。
目录总览
在这里插入图片描述

1.拦截器 /config

package com.ming.seatMonitoring.config;

import com.ming.seatMonitoring.interceptor.JWTInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @author Tcm
 *
 */
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JWTInterceptor())
                //不放行的接口;通常所有不放行
                .addPathPatterns("/**")
                //放行,
                .excludePathPatterns("/user/login");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/img/**")
                .addResourceLocations("file:C:/temp-seat/");
    }

}

2.登录、解析token接口

package com.ming.seatMonitoring.controller;

import com.auth0.jwt.interfaces.DecodedJWT;
import com.ming.seatMonitoring.pojo.DO.UserInfoDO;
import com.ming.seatMonitoring.pojo.entity.ResultBody;
import com.ming.seatMonitoring.service.LoginService;
import com.ming.seatMonitoring.util.JWTUtil;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;

/**
 * @author 小明
 * @date 2021/10/19
 * @description
 */
@RestController
@RequestMapping("/user")
public class LoginController {

    @Resource
    private LoginService loginService;

    @RequestMapping("/login")
    public ResultBody login(@RequestParam String userId,@RequestParam String passWord) {

        UserInfoDO login = loginService.login(userId,passWord);
        if (login!=null){
            HashMap<String, Object> map = new HashMap<>();
            try {
                //登录Service
                HashMap<String, String> payload = new HashMap<>();
                payload.put("userId",login.getUserId());
                payload.put("userName",login.getUserName());
                payload.put("email",login.getEmail());

                //生成JWT令牌
                String token = JWTUtil.getToken(payload);
                map.put("state",true);
                map.put("msg","认证成功");
                //响应token
                map.put("token",token);
            } catch (Exception e) {
                map.put("state",false);
                map.put("msg",e.getMessage());
            }
            System.out.println(map);
            return ResultBody.ok().data("token",map);
        }
        return ResultBody.error().message("登录失败,账号或密码错误!");
    }

    /**
     * 通过当前携带的token获取当前用户信息
     * @param request
     * @return
     */
    @RequestMapping("/explain")
    public ResultBody test(HttpServletRequest request) {
        HashMap<String, Object> map = new HashMap<>();
        //token=xx.xx.xx的头信息
        String token = request.getHeader("token");
        DecodedJWT verify = JWTUtil.verify(token);
        //通过k-v中的键取出(k不可以重复)
        String userId = verify.getClaim("userId").asString();
        String userName = verify.getClaim("userName").asString();
        String email = verify.getClaim("email").asString();
        System.out.println(userId);
        System.out.println(userName);
        System.out.println(email);

        map.put("userId",userId);
        map.put("userName",userName);
        map.put("email",email);

        return ResultBody.ok().data("info",map);
    }
}

3.token验证

package com.ming.seatMonitoring.interceptor;

import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ming.seatMonitoring.pojo.DO.UserInfoDO;
import com.ming.seatMonitoring.util.JWTUtil;
import com.ming.seatMonitoring.util.LocalUser;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;

/**
 * @author Tcm
 */
public class JWTInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HashMap<String, Object> map = new HashMap<>();
        //获取请求头中的令牌
        String token = request.getHeader("token");
        try {
            //验证令牌
            JWTUtil.verify(token);
            UserInfoDO user = JWTUtil.getUser(token);
            LocalUser.USER.set(user);
            //放行请求
            return true;
        }catch (SignatureVerificationException e){
            e.printStackTrace();
            map.put("msg","无效签名");
        }catch (TokenExpiredException e){
            e.printStackTrace();
            map.put("msg","token过期");
        }catch (Exception e){
            e.printStackTrace();
            map.put("msg","token无效");
        }
        //设置状态
        map.put("state",false);
        //将map 转为json jackson 返回信息
        String json = new ObjectMapper().writeValueAsString(map);
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().println(json);
        return false;
    }

    /**
     * 关闭当前线程
     * @param request
     * @param response
     * @param handler
     * @param modelAndView
     * @throws Exception
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        LocalUser.USER.remove();
    }
}

4.返回封装类,可以用自己的

package com.ming.seatMonitoring.pojo.entity;



import lombok.Data;
import org.springframework.beans.BeanUtils;

import java.util.HashMap;
import java.util.Map;
/**
 * @author 小明
 * @date 2021/10/19
 * @description
 */
@Data
public class ResultBody {
    //是否成功
    private Boolean success;

    //返回码
    private Integer code;

    //返回信息
    private String message;

    //返回数据
    private Map<String,Object> data = new HashMap<>();

    //附带说明
    private Map<String,String> expound = new HashMap();

    private ResultBody(){}

    /**
     * 请求成功
     * @return
     */
    public static ResultBody ok(){
        ResultBody r =new ResultBody();
        r.setSuccess(true);
        r.setCode(200);
        r.setMessage("成功");
        return r;
    }

    /**
     * 请求失败
     * @return
     */
    public static ResultBody error(){
        ResultBody resultBody = new ResultBody();
        resultBody.setSuccess(false);
        resultBody.setCode(100);
        resultBody.setMessage("失败");
        return resultBody;
    }

    /**
     * 设置返回信息
     * @param message
     * @return
     */
    public ResultBody message(String message){
        this.setMessage(message);
        return this;
    }

    /**
     * 设置返回code
     * @param code
     * @return
     */
    public ResultBody code(Integer code){
        this.setCode(code);
        return this;
    }

    /**
     * 设置返回数据
     * @param key
     * @param value
     * @return
     */
    public ResultBody data(String key,Object value){
        this.data.put(key,value);
        return this;
    }

    /**
     * 设置返回类型
     * <br/> 基本引用类型、列表类型都不能使用该方法 <br/> 对map集合、对象兼容 <br/> <strong>使用时考虑清楚</strong>
     * @param data
     * @return
     */
//    @Deprecated
    public ResultBody data(Object data){
        BeanUtils.copyProperties(data,this.data);
        return this;
    }

}

5、登录实体类

package com.ming.seatMonitoring.pojo.DO;

import com.baomidou.mybatisplus.annotation.TableField;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.Date;

/**
 * @author 小明
 * @date 2021/10/19
 * @description
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserInfoDO {
    private int id;
    private String userId;
    private String userName;
    private String passWord;
    private String email;
    @TableField(value = "createTime")
    private Date createTime;
    @TableField(value = "updateTime")
    private Date updateTime;
    @TableField(value = "deleteTime")
    private Date deleteTime;
}

6、JWT工具类

package com.ming.seatMonitoring.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.ming.seatMonitoring.pojo.DO.UserInfoDO;

import java.util.Calendar;
import java.util.Map;

/**
 * @author Tcm
 */
//抑制警告
@SuppressWarnings("all")
public class JWTUtil {
    //签名,自己设置一串复杂的字符串
    private static final String SING = "!Q@W#E$R%t";

    /**
     * 生成token
     * @param map 用户信息(userId,2019211715)
     * @return
     */
    public static String getToken(Map<String,String> map) {
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.DATE,7);//默认7天过期


        //创建jwt builder
        JWTCreator.Builder builder = JWT.create();
        //payload
        map.forEach((k,v)->{
            builder.withClaim(k,v);
        });
        //指定令牌过期时间
        String token = builder.withExpiresAt(instance.getTime())
                .sign(Algorithm.HMAC256(SING));//sign
        return token;
    }
    /**
     * 解析token
     * @param token
     * @return
     */
    public static DecodedJWT verify(String token){
        return JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
    }

    public static UserInfoDO getUser(String token){
        final UserInfoDO userInfoDO = new UserInfoDO();
        DecodedJWT verify = JWTUtil.verify(token);
        String userId = verify.getClaim("userId").asString();
        String userName = verify.getClaim("userName").asString();
        String email = verify.getClaim("email").asString();

        userInfoDO.setUserId(verify.getClaim("userId").asString());
        userInfoDO.setUserName(verify.getClaim("userName").asString());
        userInfoDO.setEmail(verify.getClaim("email").asString());
        return userInfoDO;
    }
}

7、获取当前线程

package com.ming.seatMonitoring.util;

import com.ming.seatMonitoring.pojo.DO.UserInfoDO;
import org.springframework.stereotype.Component;

/**
 * @author 小明
 * @date 2021/10/27
 * @description
 */
@Component
public class LocalUser {
    public static ThreadLocal<UserInfoDO> USER = new ThreadLocal<>();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值