SpringBoot使用拦截器、Token进行登录拦截
什么是Token?
- 客户端发送能验证自身信息的数据给服务端
- 服务端接收数据并且进行加密然后发送给客户端,这个加密的东西就是token
- 每次客户端发送请求的时候就携带这个token进行验证
- 具体情况百度
Token工具类
package com.parsley.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
*
* @Auther: Parsley
* @Date: 2021/02/02/21:24
* @Description:
*/
public class TokenUtil {
//签名的密钥
public static final String SECRET = "password";
//签发者
public static final String ISSUER = "hjj";
//面向的用户
public static final String SUBJECT = "user";
//签发时间
public static final Integer TTLMILLIS= 360000;
/**
* 生成token
*
* @param id 一般传入userName
* @return
*/
public static String createJwtToken(String id){
return createJwtToken(id,ISSUER,SUBJECT,TTLMILLIS);
}
public static String createJwtToken(String id,String subject){
return createJwtToken(id,ISSUER,subject,TTLMILLIS);
}
/**
* 生成Token
*
* @param id 编号
* @param issuer 该JWT的签发者,是否使用是可选的
* @param subject 该JWT所面向的用户,是否使用是可选的;
* @param ttlMillis 签发时间 (有效时间,过期会报错)
* @return token String
*/
public static String createJwtToken(String id, String issuer, String subject, long ttlMillis) {
//签名算法
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
//签发当前时间
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
//根据密钥生成密钥
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(SECRET);
Key signingKey = new SecretKeySpec(apiKeySecretBytes,signatureAlgorithm.getJcaName());
//Token建造器
JwtBuilder builder = Jwts.builder().setId(id).setIssuedAt(now).setSubject(subject).setIssuer(issuer).signWith(signatureAlgorithm,signingKey);
//设置过期时间
if(ttlMillis>=0){
long expMillis = nowMillis + ttlMillis;
Date exp =new Date(expMillis);
builder.setExpiration(exp);
}
//压缩
return builder.compact();
}
//解析Token
public static Claims parseJwt(String jwt){
Claims claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(SECRET)).parseClaimsJws(jwt).getBody();
return claims;
}
}
SpringBoot进行登录拦截
自定义注解–无需登录注解
被该注解进行注解的是不需要登陆的拦截器直接放行
package com.parsley.anno;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* [无需登录]
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface NoNeedLogin {
}
拦截器
注意:HandlerInterceptorAdapter已经过时了这里使用实现HandlerInterceptor接口的方式进行实现
package com.parsley.interceptor;
import com.parsley.anno.NoNeedLogin;
import com.parsley.pojo.FangDong;
import com.parsley.pojo.ZuKe;
import com.parsley.service.FangDongService;
import com.parsley.service.LoginService;
import com.parsley.service.ZuKeService;
import com.parsley.utils.TokenUtil;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Autowired
private FangDongService fangDongService;
@Autowired
private ZuKeService zuKeService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//是不是映射到方法上
boolean isHandlerMethod = handler instanceof HandlerMethod;
if(!isHandlerMethod){
System.out.println("不是方法上");
return true;
}
//不需要登录的注解
boolean isNoNeedLogin= ((HandlerMethod) handler).getMethodAnnotation(NoNeedLogin.class)!=null;
if(isNoNeedLogin){
System.out.println("无需登录");
return true;
}
//需要登录验证
String token = request.getHeader("Authorization");
if(null == token){
System.out.println("无token");
}else {
Claims claims = null;
try{
claims = TokenUtil.parseJwt(token);
}catch (Exception e){
System.out.println("token有误");
}
if (null != claims){
// Integer id = Integer.valueOf(claims.getId());
// String subject=claims.getSubject();
// if(subject.equals(LoginService.TYPE_ZU_KE)){
// ZuKe zuKe = zuKeService.getById(id);
// if(zuKe!=null){
// request.setAttribute(LoginService.TYPE_ZU_KE,zuKe);
// return true;
// }
// }else if (subject.equals(LoginService.TYPE_FANG_DONG)){
// FangDong fangDong =fangDongService.getById(id);
// if (fangDong!=null){
// request.setAttribute(LoginService.TYPE_FANG_DONG,fangDong);
// return true;
// }
// }
// return false;
}
}
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
对SpringMvc进行扩展配置拦截器
注意:不要添加@EnableWebMvc注解,该注解会导致MVC自动配置失效
package com.parsley.config;
import com.parsley.interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Created with IntelliJ IDEA.
*
* @Auther: Parsley
* @Date: 2021/02/07/20:08
* @Description:
*/
@Configuration
public class MyWebAppConfig implements WebMvcConfigurer {
@Autowired
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor).addPathPatterns("/**");
}
}
Maven
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>