需要:
懒得做登录了, 只用小程序的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,这边寄存残缺的用户
@Componentpublic 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@Componentpublic 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("没有权限执行办法"); } } }}