springboot接口訪問權限AOP實現


 

場景

現在有個系統,很多接口只需要登錄就可以訪問,但是有些接口需要授予並驗證權限。如果用注解controller的方式控制接口的權限呢?

 

1、注解聲明代碼

這個注解是要裝飾在controller接口上的。

按照一般權限的設計,有用戶(user)-角色(role)-權限(permission)三種實體,他們之間都是多對多關系。

注解聲明的時候,可以配置要驗證的角色(role)或權限(menu)。所以我這里有兩個變量。

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @Author: ivan
 * @Description:
 * @Date: Created in 19:58 18/5/28
 * @Modified By:
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Authentication {
    long[] role() default {};
    long[] menu() default {};

}

 

2、Authentication權限驗證Advice

我們以驗證角色為例。

第一步,先從controller參數的request cookie里拿到用戶登錄信息,獲取userId,我這里是card。

第二步,查詢用戶角色數據庫,獲取該user擁有哪些權限。

第三部,跟@Authentication里配置的權限進行比較,校驗成功返回數據,校驗失敗返回錯誤碼。

使用localthread記錄了權限驗證處理時間,用來進行監控。

/**
 * @Author: ivan
 * @Description:
 * @Date: Created in 20:00 18/5/28
 * @Modified By:
 */
@Aspect
@Component
@Order(-10)
public class AuthenticationAspect {

    private static Logger logger = LoggerFactory.getLogger(AuthenticationAspect.class);

    @Autowired
    private AuthDao authDao;

    ThreadLocal<Long> beginTime = new ThreadLocal<Long>();

    @Pointcut("@annotation(authentication)")
    public void AuthenticationService(Authentication authentication) {
    }

    @Around("AuthenticationService(authentication)")
    public Object doAround(ProceedingJoinPoint joinPoint, Authentication authentication) throws Throwable{
        beginTime.set(System.currentTimeMillis());
        String card = null;
        List<Long> roleList = new ArrayList<>();
        for (Object arg : joinPoint.getArgs()) {
            if (arg != null && arg.getClass() == RequestFacade.class) {
                RequestFacade request = (RequestFacade) arg;
                card = CookieUtils.getCardFromCookie(request);
                if (StringUtils.isEmpty(card)) {
                    return JsonResult.buildFailResult(-1, 1000, "權限驗證未通過", null);
                }
                List<Role> roles = authDao.getRolesByCard(card);
                for (Role role : roles) {
                    roleList.add(role.getId());
                }
                break;
            }
        }
        logger.info("[authentication] user={}, roles={}", card, roleList);
        long[] aims = authentication.role();
        boolean isPass = false;
        for (long aim : aims) {
            if (roleList.contains(aim)) {
                isPass = true;
            }
        }
        if (isPass) {
            logger.info("[authentication] authentication pass, cost time: {}", System.currentTimeMillis() - beginTime.get());
            return joinPoint.proceed();
        } else {
            beginTime.set(System.currentTimeMillis());
            logger.info("[authentication] authentication reject, cost time: {}", System.currentTimeMillis() - beginTime.get());
            return JsonResult.buildFailResult(-1, 1000, "權限驗證未通過", null);
        }

    }


}

 

3、使用方法

1、Authentication直接裝飾在controller接口上,參數是role={2},即用戶擁有2這個角色的時候擁有訪問這個接口的權限。

2、controller第一個參數要是HttpServletRequest request,不然上面從request里面拿用戶信息會失敗。(這個地方確實不方便)

/**
 * 審核接口
 *
 * @author ivan
 * @date 2018/08/02
 */
@Controller
@RequestMapping("/audit")
public class AuditController {
    private static final Logger LOGGER = LoggerFactory.getLogger(AuditController.class);
    @Resource
    private AuditService auditService;

@ResponseBody @PostMapping(value = "/review") @Authentication(role = {2}) public JsonResult review(HttpServletRequest request, @RequestBody AduitDTO aduitDTO) { LOGGER.info("[aduitDTO] video service aduitDTO={}" + aduitDTO); UserInfo userInfo = CookieUtils.getLoginInfoFromCookie(request); aduitDTO.setCard(userInfo.getCard()); int status = 0; aduitDTO.setAuditor(userInfo.getCard()); JsonResult jsonResult = null; if (ListEnum.ZERO.toString().equals(aduitDTO.getType())) { if (null != aduitDTO.getStatus() && ListEnum.ONE.toString().equals(aduitDTO.getStatus())) { status = auditService.review(aduitDTO); jsonResult = JsonResult.buildSuccessResult("審核通過"); } if (null != aduitDTO.getStatus() && ListEnum.TWO.toString().equals(aduitDTO.getStatus())) { if(StringUtils.isEmpty(aduitDTO.getReason())){ return JsonResult.buildFailResult(1, 102, "請添加不通過原因!", null); } aduitDTO.setAuditTime(DateUtils.parseDateToStr(new Date() ,"yyyy-MM-dd HH:mm:ss")); status = auditService.updateAduit(aduitDTO); jsonResult = JsonResult.buildSuccessResult("審核不通過"); } } return jsonResult; } }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM