需要:
懒得做登录了, 只用小程序的openid 来做权限治理,不援用spring的security;
步骤:
- 实现办法注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD})
public @interface HasRole {
String value();
}
简略实现一个注解,用法
@HasRole("#deviceOperate.step")
@PostMapping
public R insert(@RequestBody DeviceOperate deviceOperate) {
return success(this.deviceOperateService.save(deviceOperate));
}
- 实现HandlerInterceptor拦截器
次要用于寄存小程序的openId,这边寄存残缺的用户
@Component
public class HasRoleInterceptor implements HandlerInterceptor {
@Autowired
private UserService userService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
String openId = request.getHeader("open_id");
if (!StringUtils.hasText(openId)) {
throw new SecurityException("未找到openId");
}
User user = userService.getByOpenId(openId);
if (user == null) {
throw new SecurityException("未找到用户");
}
UserContext.set(user);
return true;
}
}
获取的用户放到上下文中,实现UserContext
public class UserContext implements AutoCloseable {
static final ThreadLocal<User> ctx = new ThreadLocal<>();
public static void set(User user) {
ctx.set(user);
}
public static User currentUser() {
return ctx.get();
}
@Override
public void close() {
ctx.remove();
}
}
- 实现Aspect办法拦截器
次要因为HandlerInterceptor实现参数获取,太过简单, 应用aspect获取更加清晰;
拦挡HasRole注解的,解析外面spel,获取须要的权限。
@Aspect
@Component
public class HasRoleAspect {
@Autowired
private UserService userService;
// Service层切点
@Pointcut("@annotation(com.hiklife.server.auth.HasRole)")
public void servicePointcut() {
}
// 切点办法执行前运行
@Before(value = "servicePointcut()")
public void doBefore(JoinPoint joinPoint) throws NoSuchMethodException {
// 获取以后拜访的class类及类名
Class<?> clazz = joinPoint.getTarget().getClass();
// 获取拜访的办法名
String methodName = joinPoint.getSignature().getName();
// 获取办法所有参数及其类型
String[] argNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames();
Object[] args = joinPoint.getArgs();
// 获取拜访的办法对象
Method method = clazz.getDeclaredMethod(methodName,
((MethodSignature) joinPoint.getSignature()).getParameterTypes());
// 判断以后拜访的办法是否存在指定注解
if (method.isAnnotationPresent(HasRole.class)) {
HasRole annotation = method.getAnnotation(HasRole.class);
// 获取注解标识值与注解形容
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression(annotation.value());
EvaluationContext context = new StandardEvaluationContext();
for (int i = 0; i < argNames.length; i++) {
context.setVariable(argNames[i], args[i]);
}
String role = String.valueOf(expression.getValue(context));
User user = UserContext.currentUser();
if (user == null || !user.getUserRole().contains(role)) {
throw new SecurityException("没有权限执行办法");
}
}
}
}
发表回复