** 简介:**对除了登录注册之外的接口做访问拦截,登录之后传递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<>();
}