=start====================本篇用springboot来搭建登录之JWT
1.添加依赖
正常的springboot依赖
JWT依赖
com.auth0
java-jwt
3.4.0
2.新建一个自定义注解配合JWT使用
@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Login {
boolean mustlogin() default true;
}
3. 生成token令牌 设置有效期为一个小时
public String generateToken(UserInfo userInfo) {
return JWT.create().withIssuedAt(new Date()).withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60))
.withSubject(userInfo.getId() == null ? null : userInfo.getId().toString())
.withIssuer(“root/admin”)
.withClaim(“username”, userInfo.getName())
.sign(getTokenByKey());
}
public Algorithm getTokenByKey() {
return Algorithm.HMAC256("Zhang147927ErMeng");//服务器生成/解析token的密匙切记不可丢失
}
4.解析token的方法
public UserInfo verifyByToken(String token) {
if (token == null || “”.equals(token)) {
return null;
}
DecodedJWT decodedJWT = null;
try {
JWTVerifier jwtVerifier = JWT.require(getTokenByKey()).build();
decodedJWT = jwtVerifier.verify(token);
Date expiresDate = decodedJWT.getExpiresAt();
if (expiresDate != null && expiresDate.after(new Date())) {
String userid = decodedJWT.getSubject();
if (userid != null && !"".equals(userid)) {
return userInfoJPA.getOne(Long.parseLong(userid));
} else {
return null;
}
}
} catch (Exception e) {
System.out.println(“校验token异常!”);
}
return null;
}
5.
编写拦截器
public class InterfaceConfig implements HandlerInterceptor {
@Autowired
public UserInfoService userInfoService;
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
//不是方法级别的直接跳过
if (!(o instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) o;
Method method = handlerMethod.getMethod();
Login login = method.getAnnotation(Login.class);
//如果有注解说明是登录接口,直接放过
if (login != null) {
return true;
}
String token = httpServletRequest.getHeader("token");
if (null == token || token.equals("") || token.equals("undefind")) {
Cookie cookie = WebUtils.getCookie(httpServletRequest, "ByToken");
if (cookie == null) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("status", httpServletResponse.SC_UNAUTHORIZED);
jsonObject.put("flag", false);
jsonObject.put("message", "Not find by token!");
httpServletResponse.getWriter().write(jsonObject.toJSONString());
httpServletResponse.getWriter().close();
return false;
}
token = cookie.getValue();
if (null == token || token.equals("") || token.equals("undefind")) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("status", httpServletResponse.SC_UNAUTHORIZED);
jsonObject.put("flag", false);
jsonObject.put("message", "Not find by token!");
httpServletResponse.getWriter().write(jsonObject.toJSONString());
httpServletResponse.getWriter().close();
return false;
}
}
UserInfo userInfo = userInfoService.verifyByToken(token);
//UserInfo userInfo = new UserInfoService().verifyByToken(token);
if (userInfo != null) {
UserInfoContent.setUserInfoContent(userInfo);
return true;
}
JSONObject jsonObject = new JSONObject();
jsonObject.put("status", httpServletResponse.SC_FORBIDDEN);
jsonObject.put("flag", false);
jsonObject.put("message", "The token is bad!");
httpServletResponse.getWriter().write(jsonObject.toJSONString());
httpServletResponse.getWriter().close();
return false;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
UserInfoContent.clearUserInfoContent();
}
}
6。使拦截器生效 顺便把跨域请求的也配置一下
@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {
@Bean
public InterfaceConfig interfaceConfig() {
return new InterfaceConfig();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(interfaceConfig()).addPathPatterns("/**");
super.addInterceptors(registry);
}
@Override//跨域配置
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("*")
.allowedOrigins("*")
.allowedHeaders("*");
super.addCorsMappings(registry);
}
}
7.自己研究的是否发现一个问题,每次登陆的时候判断完token之后再调用接口的时候如果服务器想知道用户是谁怎么办。
自己想到了这样一个方法 在每次调用接口的时候 在拦截器里把用户信息放到一个线程的变量里面 这样在其他接口就可以直接调用用户信息
public abstract class UserInfoContent {
private static final ThreadLocal userLocal = new ThreadLocal<>();
public static void setUserInfoContent(UserInfo userInfo) {
userLocal.set(userInfo);
}
public static UserInfo getUserInfoContent() {
return userLocal.get();
}
public static void clearUserInfoContent() {
userLocal.set(null);
userLocal.remove();
}
- controller编写登录接口 有@Login注解就不会判断token
@Login
@RequestMapping("/login")
@ResponseBody
public Result test(String account, String password) {
UserInfo userInfo = userInfoService.findUserInfo(account, password);
if (userInfo == null) {
return new Result(false, “the password or account is error !”);
}
//String token = userInfoService.generateToken(userInfo);*/
//Long count = userInfoJPA.finduser(account, password);
JSONObject jsonObject = new JSONObject();
jsonObject.put(“id”, userInfo.getId());
jsonObject.put(“name”, userInfo.getName());
jsonObject.put(“account”, userInfo.getAccount());
jsonObject.put(“token”, userInfoService.generateToken(userInfo));
return new Result(true, “success”, jsonObject);
}
9.编写一个接口
这个接口没有@Login注解说明需要token验证
@RequestMapping("/testBytoken")
@ResponseBody
public String test1() {
List list = userInfoJPA.findAll();
System.out.printf(list.toString());
return list.toString();
}
==========================================================
以上就是一些简单的配置和使用的过程 小白努力学习中
======end=