应一位朋友邀请写下此篇文章,不足之处请多多指教
首先我们定义一个注解 传入一个参数(传递权限的编码)
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author Sir丶雨轩
* @date 2019/06/09
*/
@Target({ ElementType.METHOD,ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {
/**
* 权限校验编码
* @return 校验编码
*/
String value() default "";
}
假设我们的项目是拥有web环境的项目 本demo的权限缓存至session中,如果是纯api项目可以将权限缓存至redis或其他缓存中
/**
* 模拟登录方法
*/
public void login(){
// 我们在这里模拟一个登录方法,具体请修改为业务代码
// 获取权限列表 存入session中
List<String> permissionList = new ArrayList<>();
// 获取request对象
HttpServletRequest request = null;
// 缓存权限列表
request.getSession().setAttribute("permissionList",permissionList);
}
然后我们的重点来了,写一个拦截器使自定义注解开始工作
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.km66.repair.support.auth.Auth;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.List;
/**
* @author Sir丶雨轩
* @date 2019/06/09
*/
@Slf4j
public class DemoAuthInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
HandlerMethod handlerMethod = null;
// 如果请求的不是方法 则直接跳过当前拦截器
if (!(handler instanceof HandlerMethod)) {
return true;
}
handlerMethod = (HandlerMethod) handler;
// 获取当前请求的方法
Method method = handlerMethod.getMethod();
// 获取方法上注解
Auth auth = method.getAnnotation(Auth.class);
// 如果方法没有注解,则去类上去获取 如果方法有则使用方法的注解,方法的注解优先级高于类的注解
if (auth == null) {
auth = handlerMethod.getBeanType().getAnnotation(Auth.class);
}
// 如果没有Auth 注解 则跳过鉴权
if (auth == null) {
return true;
}
String authorityCode = auth.value();
// 如果不包含权限编码,则表示这个接口登录就可以访问
if (StrUtil.isBlank(authorityCode)) {
Object user = request.getSession().getAttribute("user");
// 用户还没有登录
if (user == null) {
noPermission(request, response);
return false;
}
// 当前用户已经登录 完成鉴权流程
return true;
}
List<String> permissionList = (List<String>) request.getSession().getAttribute("permissionList");
assert permissionList != null;
// 当前用户没有这个地址的访问权限
if (!permissionList.contains(authorityCode)) {
noPermission(request, response);
return false;
}
return true;
}
/**
* 没有权限的处理方式
*
* @param request HttpServletRequest
* @param response HttpServletResponse
*/
public void noPermission(HttpServletRequest request, HttpServletResponse response) {
if (isAjax(request)) {
try {
OutputStream out = response.getOutputStream();
JSONObject errRet = new JSONObject();
errRet.put("code", 1);
errRet.put("msg", "您没有访问权限");
out.write(errRet.toJSONString().getBytes(Charset.defaultCharset()));
out.flush();
out.close();
} catch (IOException e) {
log.error("error", e);
}
} else {
try {
response.sendRedirect("error/noPermission");
} catch (IOException e) {
log.error("error", e);
}
}
}
/**
* 判断请求是否为ajax请求
*
* @param request HttpServletRequest
* @return Boolean
*/
public boolean isAjax(HttpServletRequest request) {
return request.getHeader("x-requested-with") != null
&& "XMLHttpRequest".equalsIgnoreCase(request.getHeader("x-requested-with"));
}
}
然后最后一步,我们把拦截器加到配置中就可以了
/**
*
* @author Sir丶雨轩
* @date 2020-06-09
*/
@Configuration
public class AppConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 权限校验拦截器,判断登录状态
registry.addInterceptor(new DemoAuthInterceptor());
}
}
评论区