b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

匿名用户]丶一个站在Java后端设计之路的男青年个人博客网站

电脑杂谈  发布时间:2019-09-14 15:04:55  来源:网络整理

java接口aop权限管理_java接口aop权限管理_aop做权限

撸了去年阿里、腾讯和携程的面试,我有一个重要看到.......>>

为什么80%的码农都做不了架构师?>>>

设计RESTFUL API的接口权限区分问题,能处理的方法有很多种,你可以直接在controller中报文,在读取service或者其他代码,也可以使用interceptor配置哪部分客户能访问哪个别接口,也可以使用shiro以及Spring Security等框架来推动权限,最后还可以采取AOP的方法来实现。

以下表述或许不准,但通俗易懂

java接口aop权限管理_aop做权限_java接口aop权限管理

这一次项目接口爆发面积广,影响作用大java接口aop权限管理,如果在每个controller中写长期类似的鉴权代码将要付出巨大的损失,同样采取BaseController的方法把这部分代码抽出以提高复杂度仍然是一件比较麻烦的事情,因此该方案直接跳过。

这是之前做一个小练手项目时使用SpringBoot配置的:

interceptor写出来不算复杂,但是接口过多的之后,要添加很多没有权限的内容放行,这个配置类就会变得十分复杂。相对于AOP来说java接口aop权限管理,AOP实现非常便捷快捷。所以当跟AOP对比时我选择了AOP。

框架通常为重型应用甚至较为复杂的认证和权限场景提供解决方案,我的平台中唯有管理员,前端,匿名三类角色,使用框架费时费力,相对比于框架,自己谋求一个权限控制步骤就非常简单了。

aop做权限_java接口aop权限管理_java接口aop权限管理

综合以下,AOP实现权限是一种更加方便的方案。

前端请求后台时,需要判定是管理员还是普通用户而是匿名客户,后台是restful api,controller本身不作权限验证。在每一个controller方法里面添加一个注解,通过AOP来判断客户header中带过来的token字段是否存在,以及token在redis的session缓存中userId到底是管理员还是普通用户,来区分权利。

java接口aop权限管理_aop做权限_java接口aop权限管理

package xyz.ruankun.machinemother.util.constant;
public enum  AuthAopConstant {
    /**
     * 管理员 普通用户 匿名者
     */
    ADMIN,
    USER,
    ANON
}

其中pass字段表明该注释是否生效,role字段表名要执行被切的那种controller中的方式应该什么权限。

java接口aop权限管理_aop做权限_java接口aop权限管理

package xyz.ruankun.machinemother.annotation;
import xyz.ruankun.machinemother.util.constant.AuthAopConstant;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value = ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Authentication {
    /**
     *  true为启用验证
     *  false为跳过验证
     * @return
     */
    boolean pass() default true;
    AuthAopConstant role() default AuthAopConstant.ANON;
}

该类就是一个切面,里面定义了一个切入点,就是插入的这个面该从那里开始执行,以及执行的逻辑等。权限代码看@Around标记的哪个方式就行了

package xyz.ruankun.machinemother.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import xyz.ruankun.machinemother.annotation.Authentication;
import xyz.ruankun.machinemother.entity.Admin;
import xyz.ruankun.machinemother.entity.User;
import xyz.ruankun.machinemother.repository.AdminRepository;
import xyz.ruankun.machinemother.repository.UserRepository;
import xyz.ruankun.machinemother.service.AdminService;
import xyz.ruankun.machinemother.service.UserInfoService;
import xyz.ruankun.machinemother.util.Constant;
import xyz.ruankun.machinemother.util.constant.AuthAopConstant;
import xyz.ruankun.machinemother.vo.ResponseEntity;
import javax.servlet.http.HttpServletRequest;
/**
 * 使用aop完成API请求时的认证和权限
 * made by Jason. Completed by mrruan
 */
@Aspect
@Component
public class AuthenticationAspect {
    public final static Logger logger = LoggerFactory.getLogger(AuthenticationAspect.class);
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private AdminService adminService;
    //去查询权限
    @Autowired
    AdminRepository adminRepository;
    @Autowired
    UserRepository userRepository;
    @Pointcut(value = "@annotation(xyz.ruankun.machinemother.annotation.Authentication)")
    public void pointcut() {}
    /**
     * 与被注释方法正确返回之后执行
     * @param joinPoint 方法执行前的参数
     * @param result 方法返回值 后续观察,是否保存
     */
    @AfterReturning(returning = "result", value = "@annotation(xyz.ruankun.machinemother.annotation.Authentication)")
    public void after(JoinPoint joinPoint, Object result) {
        logger.info("refresh token");
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            if (arg instanceof HttpServletRequest) {
                HttpServletRequest request = (HttpServletRequest) arg;
                String token = request.getParameter("token");
                if (token != null) {
                    //通过token获取id值更新token有效期
                    int userId = Integer.valueOf(userInfoService.readDataFromRedis(token));
                    String sessionKey = userInfoService.readDataFromRedis("session_key" + userId);
                    if (null == sessionKey){
                        //管理员是没有sessionkey的哟
                        adminService.updateSession(String.valueOf(userId),token,15);
                    }else
                        userInfoService.updateSession(userId,sessionKey, token,15);
                }
            }
        }
    }
    @Around("pointcut() && @annotation(authentication)")
    public  Object interceptor(ProceedingJoinPoint proceedingJoinPoint, Authentication authentication){
        boolean pass = authentication.pass();
        if(pass){
            //要验证权限
            AuthAopConstant role = authentication.role();
            //通过拿到的role,我们可以知道能处理这个请求的角色是什么
            //如果是匿名者,直接放行,如果是用户,就需要用户的权限才行,管理员则需要管理员的角色才行
            //规定一致,token放在header中
            HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder
                    .getRequestAttributes()).getRequest();
            String token = request.getHeader("token");
            AuthAopConstant realRole = authenticate(token);
            if (realRole == role) {
                //权限正确,去访问吧
                try {
                    return proceedingJoinPoint.proceed();
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                    ResponseEntity responseEntity = new ResponseEntity();
                    responseEntity.success(Constant.AOP_SERVER_ERROR, "", null);
                    return responseEntity;
                }
            }else{
                //权限错误,返回错误
                ResponseEntity responseEntity = new ResponseEntity();
                responseEntity.success(Constant.AUTH_ERROR, "permission denied,forbidden access", null);
                return responseEntity;
            }
        }else{
            //不验证权限
            try {
                return proceedingJoinPoint.proceed();
            } catch (Throwable throwable) {
                throwable.printStackTrace();
                ResponseEntity responseEntity = new ResponseEntity();
                responseEntity.success(Constant.AOP_SERVER_ERROR, "", null);
                return responseEntity;
            }
        }
    }
    /**
     * 这个方法用于判断该token所属的到底是谁(管理员? 用户? 匿名?)
     * @param token
     * @return
     */
    private AuthAopConstant authenticate(String token){
        String userId = null;
        try {
            userId = userInfoService.readDataFromRedis(token);
        } catch (Exception e) {
            e.printStackTrace();
            //读取userId错误(最大的可能是请求的header中没有token),直接返回匿名错误
            return  AuthAopConstant.ANON;
        }
        if(userId == null){
            //匿名的或者说用户过期的,没有找到session
            return AuthAopConstant.ANON;
        }else{
            Integer id;
            try {
                id = Integer.getInteger(userId);
            } catch (Exception e) {
                e.printStackTrace();
                //都抛出了异常了,这个userId是假的,直接匿名者
                return AuthAopConstant.ANON;
            }
            Admin admin = adminRepository.findById(id).get();
            if(null != admin){
                //是管理员
                return AuthAopConstant.ADMIN;
            }else{
                User user = userRepository.findById(id).get();
                if (null != user){
                    //是用户
                    return AuthAopConstant.USER;
                }else{
                    //没有发现它是用户,假的
                   return AuthAopConstant.ANON;
                }
            }
        }
    }
}

拦截了一下登录方式,用来测试的,起作用了。注意一下,我的逻辑中是把token放在header中了的。

    //拦截判断是不是管理员
    @GetMapping("/token")
    @Authentication(pass = true,role = AuthAopConstant.ADMIN)
    public ResponseEntity login(String account,String password){
        Integer rs = adminService.adminLogin(account,password);
        ResponseEntity responseEntity = new ResponseEntity();
        if(rs.equals(Constant.LOGIN_NO_USER)){
            //登录失败了,因为没有找到对应的用户
            responseEntity.error(Constant.LOGIN_NO_USER,"no such admin",null);
        }else {
            //登录成功了,送出token
            String token = userInfoService.readDataFromRedis(String.valueOf(rs.intValue()));
            responseEntity.success(Constant.LOGIN_SUCCESS,"login success",token);
        }
        return responseEntity;
    }

695856371Web网页设计师②群 |喜欢本站的同学可以收藏本站,或者加入我们大家一起来交流技术!

欢迎来到梁钟霖个人博客网站。本个人博客网页提供最新的站长新闻,各种互联网资讯。还提供个人博客模板,最新最全的java教程,java面试题。在此我将尽我最大所能将此个人博客网站做的最好!谢谢你们,愿各位一起进步!


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-122839-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...