package com.baidu.disconf.web.service.roleres.service; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.aspectj.lang.ProceedingJoinPoint; 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.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.baidu.disconf.web.service.roleres.constant.RoleResourceConstant; import com.baidu.disconf.web.service.user.dto.Visitor; import com.baidu.dsp.common.exception.AccessDeniedException; import com.baidu.ub.common.commons.ThreadContext; /** * 判断用户是否具有请求方法的访问权 */ @Aspect public class RoleResourceAspect { protected static final Logger LOG = LoggerFactory.getLogger(RoleResourceAspect.class); @Autowired private RoleResourceMgr roleResMgr; // 不用进行权限控制 private List<String> noAuthCheckUrl; @Pointcut(value = "execution(public * *(..))") public void anyPublicMethod() { } /** * 判断当前用户对访问的方法是否有权限 * * @param pjp 方法 * @param requestMapping 方法上的annotation * * @return * * @throws Throwable */ @Around("anyPublicMethod() && @annotation(requestMapping) && !@annotation(com.baidu.dsp.common.annotation.NoAuth)") public Object decideAccess(ProceedingJoinPoint pjp, RequestMapping requestMapping) throws Throwable { // 获取method上的url,若未标注value则默认为空字符串 String[] values = requestMapping.value(); String methodUrl = ""; if (values.length != 0) { methodUrl = values[0]; } String clsUrl = pjp.getTarget().getClass().getAnnotation(RequestMapping.class).value()[0]; // 拼接method和class上标注的url if (!clsUrl.endsWith(RoleResourceConstant.URL_SPLITOR) && !methodUrl.startsWith(RoleResourceConstant.URL_SPLITOR)) { clsUrl += RoleResourceConstant.URL_SPLITOR; } String urlPattarn = clsUrl + methodUrl; if (!urlPattarn.endsWith(RoleResourceConstant.URL_SPLITOR)) { urlPattarn += RoleResourceConstant.URL_SPLITOR; } if (noAuthCheckUrl != null && noAuthCheckUrl.contains(urlPattarn)) { LOG.info("don't need to check this url: " + urlPattarn); } else { // 获取method上标注的http method,若未标注method则默认为GET RequestMethod[] methods = requestMapping.method(); RequestMethod methodType = RequestMethod.GET; if (methods.length != 0) { methodType = methods[0]; } String urlInfo = urlPattarn + ", method:" + methodType.toString(); // 获取用户角色 Visitor visitor = ThreadContext.getSessionVisitor(); if (visitor == null) { LOG.warn("No session visitor!"); throw new AccessDeniedException("No session visitor! " + urlInfo); } Integer roleId = visitor.getRoleId(); String visitorInfo = ", UserId:" + visitor.getId() + ", RoleId:" + roleId; Boolean isPriviledged = true; // 判断用户是否有权限访问方法 if (!this.isMethodAccessible(urlPattarn, methodType, roleId)) { isPriviledged = false; throw new AccessDeniedException("Access Denied: " + urlInfo + visitorInfo); } LOG.info("Accessing URL:" + urlInfo + visitorInfo + ", Is priviledged:" + isPriviledged.toString()); } Object rtnOb = null; try { // 执行方法 rtnOb = pjp.proceed(); } catch (Throwable t) { LOG.info(t.getMessage()); throw t; } return rtnOb; } /** * 用户角色是否有权限访问当前方法 * * @param url * @param method * @param userRoleId * * @return */ private boolean isMethodAccessible(String url, RequestMethod method, Integer userRoleId) { boolean accessible = false; List<Integer> roleIdList = getPriviledgedRoles(url, method); if (roleIdList.contains(userRoleId)) { accessible = true; } return accessible; } /** * 获取可以访问方法的角色id列表 * * @param url * @param method * * @return */ private List<Integer> getPriviledgedRoles(String url, RequestMethod method) { Map<String, Map<RequestMethod, List<Integer>>> roleResMap = roleResMgr.getAllAsMap(); Map<RequestMethod, List<Integer>> methodMap = roleResMap.get(url); if (methodMap == null) { return new ArrayList<Integer>(); } List<Integer> roleIdList = methodMap.get(method); if (roleIdList == null) { roleIdList = new ArrayList<Integer>(); } return roleIdList; } public List<String> getNoAuthCheckUrl() { return noAuthCheckUrl; } public void setNoAuthCheckUrl(List<String> noAuthCheckUrl) { this.noAuthCheckUrl = noAuthCheckUrl; } }