用户权限验证
intercept拦截器使用
之前在进行登录状态判断时用的是intercept拦截器进行拦截处理,配合Jwt生成token,在客户端发送请求时检查请求头里有无携带token,并验证token是否合法,否则就拦截该请求返回错误提示,对登录状态判断时我觉得使用拦截器比较方便,代码量少也能实现功能
在配置拦截器里只需将需要拦截的地址添加进去即可
@Configuration
public class InterceptConfig implements WebMvcConfigurer {
@Resource
InterceptImpl intercept;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(intercept)
.addPathPatterns("/admin/**") //拦截admin下的所有请求
.excludePathPatterns("/admin/login/**"); //设置放行地址
}
@Override
public void addCorsMappings(CorsRegistry registry) {
//设置允许跨域的路径
registry.addMapping("/")
//设置允许跨域请求的域名
.allowedOriginPatterns("*")
//是否允许证书 不再默认开启
.allowCredentials(true)
//设置允许的方法
.allowedMethods("*")
//跨域允许时间
.maxAge(3600);
}
}
拦截器实现类继承HandlerInterceptor接口,实现preHandle,postHandle,afterCompletion方法
在preHandle里写验证权限的操作,例如:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");
response.setHeader("Access-Control-Allow-Origin", "*");
//在这里声明需要在header里携带的参数,比如token
response.setHeader("Access-Control-Allow-Headers", "Content-Type,Content-Length, Authorization, Accept,X-Requested-With,token");
response.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
if (!(handler instanceof HandlerMethod)) {
return true;
}
JWTUtils.verifyToken(token, String.valueOf(userId),response);
return true;
}
剩下两个方法看自己需求,可写可不写 ,到这里是不是感觉使用拦截器和jwt配合进行权限验证非常方便,但也有弊端,例如:当你需要对不同的请求进行不同的验证时,就好比后台管理系统,不同的用户能做的操作不同,界面显示的菜单选项也不同,这是使用aop自定义注解来实现就比较好,总的来说intercept和aop各有千秋
AOP 自定义注解实现
直接说用法吧,网上关于aop的介绍一大堆,(放张图意思意思)
配置自定义注解:
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.PARAMETER})
//@target里面参数 ElementType.METHOD说明可以用在方法上 ElementType.PARAMETER 可以用在字段上 ElementType.TYPE 可以用在类上
@Retention(RetentionPolicy.RUNTIME) //设置运行时不被丢弃
@Documented //可以被javadoc标注为文档,可写可不写,看自己需求
public @interface TokenCheck {
String token() default "";
}
自定义注解使用:
//在方法上使用
@TokenCheck
@GetMapping("login/{userName}/{password}")
public ResultVo login(@PathVariable String userName,@PathVariable String password){
return userService.login(userName, password);
}
//在字段上使用
@TokenCheck
@GetMapping("TokenCheck/{demo}")
public ResultVo demoCheck(@TokenCheck @PathVariable String demo) {
return userService.TokenCheck(demo);
}
//两种用法区别不大
aop切面拦截功能实现:
@Aspect
@Component
@Order(1) //括号里面数字代表执行顺序,当有多个拦截时刻自定义执行顺序
public class TokenCheck {
@Pointcut("@annotation(com.xqj.common.utils.annotation.TokenCheck)")
public void check(){
}
@Around("check()")
public Object demoCheck(ProceedingJoinPoint pjp) throws Throwable {
/**
* 填写处理注解事务逻辑
*/
System.out.println("进AoP了!!");
Signature signature = pjp.getSignature(); //可以获取有关包方法的信息
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes;
HttpServletRequest request = attributes.getRequest(); //获得HttpServletRequest请求对象,主要用来获取token
return pjp.proceed(); //放行
}
}
到这里aop的自定义注解就配置好了,比intercept稍微繁琐一点
Jwt 的使用
引入依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
配置jwtUtils类
public class JwtUtils {
/**
* 签发token对象
* @param uid
* @param userName
* @return
*/
public static String createToken(String uid,String userName){
Calendar nowTime = Calendar.getInstance();
nowTime.add(Calendar.HOUR,12);
Date time = nowTime.getTime();
return JWT.create().withAudience(uid)
.withIssuedAt(new Date()) //发行时间
.withExpiresAt(time) //有效期限
.withClaim("userName",userName)
.sign(Algorithm.HMAC256(uid+"xqj"));
}
public static void verifyToken(String token, String secret){
DecodedJWT jwt = null;
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secret+"xqj")).build();
jwt = verifier.verify(token);
} catch (Exception e) {
throw new RuntimeException("tokenError");
}
}
/**
* 获取签发对象
*/
public static String getAudience(String token) {
String audience = null;
try {
audience = JWT.decode(token).getAudience().get(0);
} catch (JWTDecodeException j) {
//这里是token解析失败
throw new RuntimeException();
}
return audience;
}
/**
* 通过载荷名字获取载荷的值
*/
public static Claim getClaimByName(String token, String name){
return JWT.decode(token).getClaim(name);
}
}
到这jwt就可以直接使用了,生成token令牌、验证令牌合法性等等
博客地址: 徐启君的个人博客 xqijun.top