分享

spring security 的@Secured 标注在Controller上

 windli笔记 2013-03-22

创建SecuredInterceptor类继承HandlerInterceptorAdapter类

重写preHandle方法

 

  1. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
  2.     if(getLoginUrl() != null && request.getUserPrincipal() == null) {  
  3.         throw new ModelAndViewDefiningException(new ModelAndView("redirect:" + getLoginUrl()));  
  4.     }  
  5.     try {  
  6.         ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);  
  7.         Method handlerMethod = methodResolver.resolveHandlerMethod(request);  
  8.         String[] secureds = getMethodSecured(handlerMethod);  
  9.         if(secureds == null) {  
  10.             return true;  
  11.         }  
  12.         if (logger.isDebugEnabled()) {  
  13.             logger.debug("[" + handlerMethod.getDeclaringClass() + "] method:[" + handlerMethod.getName() + "] role:" + Arrays.asList(secureds));  
  14.         }  
  15.         for(String secured : secureds) {  
  16.             if(!request.isUserInRole(secured)) {  
  17.                 if(getDenyUrl() != null) {  
  18.                     throw new ModelAndViewDefiningException(new ModelAndView("redirect:" + getDenyUrl()));  
  19.                 }  
  20.                 response.sendError(HttpServletResponse.SC_FORBIDDEN,secured);  
  21.                 return false;  
  22.             }  
  23.         }  
  24.         return true;  
  25.     } catch (NoSuchRequestHandlingMethodException ex) {  
  26.         response.sendError(HttpServletResponse.SC_NOT_FOUND);  
  27.         return false;  
  28.     }  
  29. }  

 

创建 RequestMappingInfo 类 重写equals和hashCode方法

 

  1. private static class RequestMappingInfo {  
  2.   
  3.     public String[] paths = new String[0];  
  4.   
  5.     public RequestMethod[] methods = new RequestMethod[0];  
  6.   
  7.     public String[] params = new String[0];  
  8.   
  9.     public boolean equals(Object obj) {  
  10.         RequestMappingInfo other = (RequestMappingInfo) obj;  
  11.         return (Arrays.equals(this.paths, other.paths) && Arrays.equals(this.methods, other.methods) && Arrays  
  12.                 .equals(this.params, other.params));  
  13.     }  
  14.   
  15.     public int hashCode() {  
  16.         return (Arrays.hashCode(this.paths) * 29 + Arrays.hashCode(this.methods) * 31 + Arrays  
  17.                 .hashCode(this.params));  
  18.     }  
  19. }  

 

在创建 ServletHandlerMethodResolver 类 继承HandlerMethodResolver

此类用于反射Controller类中的全部方法

 

  1. private class ServletHandlerMethodResolver extends HandlerMethodResolver {  
  2.   
  3.     public ServletHandlerMethodResolver(Class<?> handlerType) {  
  4.         init(handlerType);  
  5.     }  
  6.   
  7.     public Method resolveHandlerMethod(HttpServletRequest request) throws ServletException {  
  8.         String lookupPath = urlPathHelper.getLookupPathForRequest(request);  
  9.         Map<RequestMappingInfo, Method> targetHandlerMethods = new LinkedHashMap<RequestMappingInfo, Method>();  
  10.         Map<RequestMappingInfo, String> targetPathMatches = new LinkedHashMap<RequestMappingInfo, String>();  
  11.         String resolvedMethodName = null;  
  12.         for (Method handlerMethod : getHandlerMethods()) {  
  13.             RequestMappingInfo mappingInfo = new RequestMappingInfo();  
  14.             RequestMapping mapping = AnnotationUtils.findAnnotation(handlerMethod, RequestMapping.class);  
  15.             mappingInfo.paths = mapping.value();  
  16.             if (!hasTypeLevelMapping() || !Arrays.equals(mapping.method(), getTypeLevelMapping().method())) {  
  17.                 mappingInfo.methods = mapping.method();  
  18.             }  
  19.             if (!hasTypeLevelMapping() || !Arrays.equals(mapping.params(), getTypeLevelMapping().params())) {  
  20.                 mappingInfo.params = mapping.params();  
  21.             }  
  22.             boolean match = false;  
  23.             if (mappingInfo.paths.length > 0) {  
  24.                 for (String mappedPath : mappingInfo.paths) {  
  25.                     if (isPathMatch(mappedPath, lookupPath)) {  
  26.                         if (checkParameters(mappingInfo, request)) {  
  27.                             match = true;  
  28.                             targetPathMatches.put(mappingInfo, mappedPath);  
  29.                         } else {  
  30.                             break;  
  31.                         }  
  32.                     }  
  33.                 }  
  34.             } else {  
  35.                 // No paths specified: parameter match sufficient.  
  36.                 match = checkParameters(mappingInfo, request);  
  37.                 if (match && mappingInfo.methods.length == 0 && mappingInfo.params.length == 0  
  38.                         && resolvedMethodName != null && !resolvedMethodName.equals(handlerMethod.getName())) {  
  39.                     match = false;  
  40.                 }  
  41.             }  
  42.             if (match) {  
  43.                 Method oldMappedMethod = targetHandlerMethods.put(mappingInfo, handlerMethod);  
  44.                 if (oldMappedMethod != null && oldMappedMethod != handlerMethod) {  
  45.                     if (methodNameResolver != null && mappingInfo.paths.length == 0) {  
  46.                         if (resolvedMethodName == null) {  
  47.                             resolvedMethodName = methodNameResolver.getHandlerMethodName(request);  
  48.                         }  
  49.                         if (!resolvedMethodName.equals(oldMappedMethod.getName())) {  
  50.                             oldMappedMethod = null;  
  51.                         }  
  52.                         if (!resolvedMethodName.equals(handlerMethod.getName())) {  
  53.                             if (oldMappedMethod != null) {  
  54.                                 targetHandlerMethods.put(mappingInfo, oldMappedMethod);  
  55.                                 oldMappedMethod = null;  
  56.                             } else {  
  57.                                 targetHandlerMethods.remove(mappingInfo);  
  58.                             }  
  59.                         }  
  60.                     }  
  61.                     if (oldMappedMethod != null) {  
  62.                         throw new IllegalStateException(  
  63.                                 "Ambiguous handler methods mapped for HTTP path '"  
  64.                                         + lookupPath  
  65.                                         + "': {"  
  66.                                         + oldMappedMethod  
  67.                                         + ", "  
  68.                                         + handlerMethod  
  69.                                         + "}. If you intend to handle the same path in multiple methods, then factor "  
  70.                                         + "them out into a dedicated handler class with that path mapped at the type level!");  
  71.                     }  
  72.                 }  
  73.             }  
  74.         }  
  75.         if (targetHandlerMethods.size() == 1) {  
  76.             return targetHandlerMethods.values().iterator().next();  
  77.         } else if (!targetHandlerMethods.isEmpty()) {  
  78.             RequestMappingInfo bestMappingMatch = null;  
  79.             String bestPathMatch = null;  
  80.             for (RequestMappingInfo mapping : targetHandlerMethods.keySet()) {  
  81.                 String mappedPath = targetPathMatches.get(mapping);  
  82.                 if (bestMappingMatch == null) {  
  83.                     bestMappingMatch = mapping;  
  84.                     bestPathMatch = mappedPath;  
  85.                 } else {  
  86.                     if (isBetterPathMatch(mappedPath, bestPathMatch, lookupPath)  
  87.                             || (!isBetterPathMatch(bestPathMatch, mappedPath, lookupPath) && (isBetterMethodMatch(  
  88.                                     mapping, bestMappingMatch) || (!isBetterMethodMatch(bestMappingMatch, mapping) && isBetterParamMatch(  
  89.                                     mapping, bestMappingMatch))))) {  
  90.                         bestMappingMatch = mapping;  
  91.                         bestPathMatch = mappedPath;  
  92.                     }  
  93.                 }  
  94.             }  
  95.             return targetHandlerMethods.get(bestMappingMatch);  
  96.         } else {  
  97.             throw new NoSuchRequestHandlingMethodException(lookupPath, request.getMethod(), request  
  98.                     .getParameterMap());  
  99.         }  
  100.     }  
  101.   
  102.     private boolean isPathMatch(String mappedPath, String lookupPath) {  
  103.         if (mappedPath.equals(lookupPath) || pathMatcher.match(mappedPath, lookupPath)) {  
  104.             return true;  
  105.         }  
  106.         boolean hasSuffix = (mappedPath.indexOf('.') != -1);  
  107.         if (!hasSuffix && pathMatcher.match(mappedPath + ".*", lookupPath)) {  
  108.             return true;  
  109.         }  
  110.         return (!mappedPath.startsWith("/") && (lookupPath.endsWith(mappedPath)  
  111.                 || pathMatcher.match("/**/" + mappedPath, lookupPath) || (!hasSuffix && pathMatcher.match("/**/"  
  112.                 + mappedPath + ".*", lookupPath))));  
  113.     }  
  114.   
  115.     private boolean checkParameters(RequestMappingInfo mapping, HttpServletRequest request) {  
  116.         return checkRequestMethod(mapping.methods, request) && checkParameters(mapping.params, request);  
  117.     }  
  118.   
  119.     private boolean checkRequestMethod(RequestMethod[] methods, HttpServletRequest request) {  
  120.         if (!ObjectUtils.isEmpty(methods)) {  
  121.             boolean match = false;  
  122.             for (RequestMethod method : methods) {  
  123.                 if (method.name().equals(request.getMethod())) {  
  124.                     match = true;  
  125.                 }  
  126.             }  
  127.             if (!match) {  
  128.                 return false;  
  129.             }  
  130.         }  
  131.         return true;  
  132.     }  
  133.   
  134.     private boolean checkParameters(String[] params, HttpServletRequest request) {  
  135.         if (!ObjectUtils.isEmpty(params)) {  
  136.             for (String param : params) {  
  137.                 int separator = param.indexOf('=');  
  138.                 if (separator == -1) {  
  139.                     if (param.startsWith("!")) {  
  140.                         if (WebUtils.hasSubmitParameter(request, param.substring(1))) {  
  141.                             return false;  
  142.                         }  
  143.                     } else if (!WebUtils.hasSubmitParameter(request, param)) {  
  144.                         return false;  
  145.                     }  
  146.                 } else {  
  147.                     String key = param.substring(0, separator);  
  148.                     String value = param.substring(separator + 1);  
  149.                     if (!value.equals(request.getParameter(key))) {  
  150.                         return false;  
  151.                     }  
  152.                 }  
  153.             }  
  154.         }  
  155.         return true;  
  156.     }  
  157.   
  158.     private boolean isBetterPathMatch(String mappedPath, String mappedPathToCompare, String lookupPath) {  
  159.         return (mappedPath != null && (mappedPathToCompare == null || mappedPath.equals(lookupPath) || mappedPathToCompare  
  160.                 .length() < mappedPath.length()));  
  161.     }  
  162.   
  163.     private boolean isBetterMethodMatch(RequestMappingInfo mapping, RequestMappingInfo mappingToCompare) {  
  164.         return (mappingToCompare.methods.length == 0 && mapping.methods.length > 0);  
  165.     }  
  166.   
  167.     private boolean isBetterParamMatch(RequestMappingInfo mapping, RequestMappingInfo mappingToCompare) {  
  168.         return (mappingToCompare.params.length < mapping.params.length);  
  169.     }  
  170.   
  171. }  

 

下面是俩个内部使用的工具方法

 

  1. private String[] getMethodSecured(Method handlerMethod) {  
  2.         String[] secureds = this.methodPrivilegeCache.get(handlerMethod);  
  3.         if (secureds == null) {  
  4.             Secured s = handlerMethod.getAnnotation(Secured.class);  
  5.             if(s != null) {  
  6.                 secureds = s.value();  
  7.                 this.methodPrivilegeCache.put(handlerMethod, secureds);  
  8.             }  
  9.         }  
  10.         return secureds;  
  11.     }  
  12.   
  13.     private ServletHandlerMethodResolver getMethodResolver(Object handler) {  
  14.         Class handlerClass = ClassUtils.getUserClass(handler);  
  15.         ServletHandlerMethodResolver resolver = this.methodResolverCache.get(handlerClass);  
  16.         if (resolver == null) {  
  17.             resolver = new ServletHandlerMethodResolver(handlerClass);  
  18.             this.methodResolverCache.put(handlerClass, resolver);  
  19.         }  
  20.         return resolver;  
  21.     }  

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多