公司项目JAVA开发规范总结(四)——权限规范

本文介绍了如何通过拦截器和注解在Spring MVC应用中实现用户权限验证,包括AdminAccessRightsInterceptor和TokenAuthenticationInterceptor的使用,以及如何通过UserAuthorized注解和切面进行更细粒度的权限控制。重点讨论了不同实现方式的优缺点和优化建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

四、权限规范

1、拦截器+MVC实现

概述:通过拦截去设置用户是否能够访问该接口

AdminAccessRightsInterceptor:该拦截器只允许管理员及以上身份才能访问,

TokenAuthenticationInterceptor:这两个拦截器都是用来进行token校验的,判断是否是系统用户,是否能访问接口。

通过token去获取用户信息,获取成功则说明token校验通过,可进行接口访问

public class TokenAuthenticationInterceptor implements HandlerInterceptor  {
 @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object object) throws Exception {
    	String token = request.getHeader("Authorization");
    	Object obj = checkToken(token);
    	if(obj.getError()==0&&StringUtils.isNotBlank(obj.getData().get("UserID"))) {
		    request.setAttribute("acc_schoolid", obj.getData().get("SchoolID"));
		    request.setAttribute("acc_userid", obj.getData().get("UserID"));
		    try {
		        request.setAttribute("acc_username", URLDecoder.decode(obj.getData().get("UserName"),"UTF-8"));
		    } catch (Exception e) {
		        log.error("token认证成功,转码用户名称出现异常:{}",e);
		        request.setAttribute("acc_username", obj.getData().get("UserID"));
		    }
		    request.setAttribute("acc_usertype", obj.getData().get("UserType"));
		    request.setAttribute("acc_userclass", obj.getData().get("UserClass"));
		    request.setAttribute("acc_studylevel", obj.getData().get("StudyLevel"));
		    request.setAttribute("acc_photoPath", URLDecoder.decode(obj.getData().get("PhotoPath"),"UTF-8"));
		
		    return true;
		
		}else {
		
		    returnErrorResponse(new PacketHttpRes_V32<>(ReturnCode.token_false_code,ReturnCode.token_false_message,ReturnCode.err_nomean_code,ReturnCode.err_nomean_message,null),response); 
		
		    log.error("token认证失败,未认证的请求。error={},用户ID为{}",obj.getError(),obj.getData().get("UserID"));
		
		    return false;
		
		}
    }
}

将获取到的用户信息进行存储到request中,当需要用户信息的时候则从中拿出来使用

 registry.addInterceptor(tokenAuthenticationInterceptor)
		                                   .addPathPatterns("/TeachingPlan/**")
		                                   .excludePathPatterns("/TeachingPlan/AddApplyInfo")

当我们写一些接口的时候,需时刻注意其权限规范,要注意其是否在拦截器的链路范围内,是否符合权限要求。

2、注解+切面实现

使用拦截器做安全权限校验

优点:可对于相同前缀的访问路径做同样的权限处理

 registry.addInterceptor(tokenAuthenticationInterceptor)
		                                   .addPathPatterns("/TeachingPlan/**")
		                                   .excludePathPatterns("/TeachingPlan/AddApplyInfo")

缺点:如果用户拥有多角色多权限,那就得编写多个拦截器,配置多次该路径,最主要的是权限的区分不够细致,如果配置细致针对到每个接口,那么就会显得代码冗余杂乱,也失去了它自身的优点。

优化方案:

概述:编写UserAuthorized注释和切面实现类,通过对于添加了该注释的接口方法,当用户访问时进行切面拦截处理,进行前置的token校验与身份权限校验。

UserAuthorized注释:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface UserAuthorized {
    
	//是否起作用
    boolean required() default true;
	//需要拥有身份权限才能访问
    String[] params() default {};

}

UserAuthorizeAspect切面实现类:

@Slf4j
@Aspect
@Component
public class UserAuthorizeAspect {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private GetAddressBySysId getAddressBySysId;

    @Autowired
    private BaseRequest baseRequest;

    @Pointcut("@annotation(com.lancoo.common.security.annotation.UserAuthorized)")
    private void pointcut() {
    }

    @Before("pointcut()")
    public void before(JoinPoint joinPoint){
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        UserAuthorized authorized = method.getAnnotation(UserAuthorized.class);
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String token = getToken(request);
       	Object obj = getUser(token);
        checkLoginResult(request, obj);
        checkUserPower(authorized, request);

    }

    @Around("pointcut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        return joinPoint.proceed();
    }

    /**
     * 在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
     *
     * @param joinPoint
     */
    @AfterReturning("pointcut()")
    public void doAfterReturning(JoinPoint joinPoint) {
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值