创建SecuredInterceptor类继承HandlerInterceptorAdapter类
重写preHandle方法
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if(getLoginUrl() != null && request.getUserPrincipal() == null) { throw new ModelAndViewDefiningException(new ModelAndView("redirect:" + getLoginUrl())); } try { ServletHandlerMethodResolver methodResolver = getMethodResolver(handler); Method handlerMethod = methodResolver.resolveHandlerMethod(request); String[] secureds = getMethodSecured(handlerMethod); if(secureds == null) { return true; } if (logger.isDebugEnabled()) { logger.debug("[" + handlerMethod.getDeclaringClass() + "] method:[" + handlerMethod.getName() + "] role:" + Arrays.asList(secureds)); } for(String secured : secureds) { if(!request.isUserInRole(secured)) { if(getDenyUrl() != null) { throw new ModelAndViewDefiningException(new ModelAndView("redirect:" + getDenyUrl())); } response.sendError(HttpServletResponse.SC_FORBIDDEN,secured); return false; } } return true; } catch (NoSuchRequestHandlingMethodException ex) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return false; } }
创建 RequestMappingInfo 类 重写equals和hashCode方法
private static class RequestMappingInfo { public String[] paths = new String[0]; public RequestMethod[] methods = new RequestMethod[0]; public String[] params = new String[0]; public boolean equals(Object obj) { RequestMappingInfo other = (RequestMappingInfo) obj; return (Arrays.equals(this.paths, other.paths) && Arrays.equals(this.methods, other.methods) && Arrays .equals(this.params, other.params)); } public int hashCode() { return (Arrays.hashCode(this.paths) * 29 + Arrays.hashCode(this.methods) * 31 + Arrays .hashCode(this.params)); } }
在创建 ServletHandlerMethodResolver 类 继承HandlerMethodResolver
此类用于反射Controller类中的全部方法
private class ServletHandlerMethodResolver extends HandlerMethodResolver { public ServletHandlerMethodResolver(Class<?> handlerType) { init(handlerType); } public Method resolveHandlerMethod(HttpServletRequest request) throws ServletException { String lookupPath = urlPathHelper.getLookupPathForRequest(request); Map<RequestMappingInfo, Method> targetHandlerMethods = new LinkedHashMap<RequestMappingInfo, Method>(); Map<RequestMappingInfo, String> targetPathMatches = new LinkedHashMap<RequestMappingInfo, String>(); String resolvedMethodName = null; for (Method handlerMethod : getHandlerMethods()) { RequestMappingInfo mappingInfo = new RequestMappingInfo(); RequestMapping mapping = AnnotationUtils.findAnnotation(handlerMethod, RequestMapping.class); mappingInfo.paths = mapping.value(); if (!hasTypeLevelMapping() || !Arrays.equals(mapping.method(), getTypeLevelMapping().method())) { mappingInfo.methods = mapping.method(); } if (!hasTypeLevelMapping() || !Arrays.equals(mapping.params(), getTypeLevelMapping().params())) { mappingInfo.params = mapping.params(); } boolean match = false; if (mappingInfo.paths.length > 0) { for (String mappedPath : mappingInfo.paths) { if (isPathMatch(mappedPath, lookupPath)) { if (checkParameters(mappingInfo, request)) { match = true; targetPathMatches.put(mappingInfo, mappedPath); } else { break; } } } } else { // No paths specified: parameter match sufficient. match = checkParameters(mappingInfo, request); if (match && mappingInfo.methods.length == 0 && mappingInfo.params.length == 0 && resolvedMethodName != null && !resolvedMethodName.equals(handlerMethod.getName())) { match = false; } } if (match) { Method oldMappedMethod = targetHandlerMethods.put(mappingInfo, handlerMethod); if (oldMappedMethod != null && oldMappedMethod != handlerMethod) { if (methodNameResolver != null && mappingInfo.paths.length == 0) { if (resolvedMethodName == null) { resolvedMethodName = methodNameResolver.getHandlerMethodName(request); } if (!resolvedMethodName.equals(oldMappedMethod.getName())) { oldMappedMethod = null; } if (!resolvedMethodName.equals(handlerMethod.getName())) { if (oldMappedMethod != null) { targetHandlerMethods.put(mappingInfo, oldMappedMethod); oldMappedMethod = null; } else { targetHandlerMethods.remove(mappingInfo); } } } if (oldMappedMethod != null) { throw new IllegalStateException( "Ambiguous handler methods mapped for HTTP path '" + lookupPath + "': {" + oldMappedMethod + ", " + handlerMethod + "}. If you intend to handle the same path in multiple methods, then factor " + "them out into a dedicated handler class with that path mapped at the type level!"); } } } } if (targetHandlerMethods.size() == 1) { return targetHandlerMethods.values().iterator().next(); } else if (!targetHandlerMethods.isEmpty()) { RequestMappingInfo bestMappingMatch = null; String bestPathMatch = null; for (RequestMappingInfo mapping : targetHandlerMethods.keySet()) { String mappedPath = targetPathMatches.get(mapping); if (bestMappingMatch == null) { bestMappingMatch = mapping; bestPathMatch = mappedPath; } else { if (isBetterPathMatch(mappedPath, bestPathMatch, lookupPath) || (!isBetterPathMatch(bestPathMatch, mappedPath, lookupPath) && (isBetterMethodMatch( mapping, bestMappingMatch) || (!isBetterMethodMatch(bestMappingMatch, mapping) && isBetterParamMatch( mapping, bestMappingMatch))))) { bestMappingMatch = mapping; bestPathMatch = mappedPath; } } } return targetHandlerMethods.get(bestMappingMatch); } else { throw new NoSuchRequestHandlingMethodException(lookupPath, request.getMethod(), request .getParameterMap()); } } private boolean isPathMatch(String mappedPath, String lookupPath) { if (mappedPath.equals(lookupPath) || pathMatcher.match(mappedPath, lookupPath)) { return true; } boolean hasSuffix = (mappedPath.indexOf('.') != -1); if (!hasSuffix && pathMatcher.match(mappedPath + ".*", lookupPath)) { return true; } return (!mappedPath.startsWith("/") && (lookupPath.endsWith(mappedPath) || pathMatcher.match("/**/" + mappedPath, lookupPath) || (!hasSuffix && pathMatcher.match("/**/" + mappedPath + ".*", lookupPath)))); } private boolean checkParameters(RequestMappingInfo mapping, HttpServletRequest request) { return checkRequestMethod(mapping.methods, request) && checkParameters(mapping.params, request); } private boolean checkRequestMethod(RequestMethod[] methods, HttpServletRequest request) { if (!ObjectUtils.isEmpty(methods)) { boolean match = false; for (RequestMethod method : methods) { if (method.name().equals(request.getMethod())) { match = true; } } if (!match) { return false; } } return true; } private boolean checkParameters(String[] params, HttpServletRequest request) { if (!ObjectUtils.isEmpty(params)) { for (String param : params) { int separator = param.indexOf('='); if (separator == -1) { if (param.startsWith("!")) { if (WebUtils.hasSubmitParameter(request, param.substring(1))) { return false; } } else if (!WebUtils.hasSubmitParameter(request, param)) { return false; } } else { String key = param.substring(0, separator); String value = param.substring(separator + 1); if (!value.equals(request.getParameter(key))) { return false; } } } } return true; } private boolean isBetterPathMatch(String mappedPath, String mappedPathToCompare, String lookupPath) { return (mappedPath != null && (mappedPathToCompare == null || mappedPath.equals(lookupPath) || mappedPathToCompare .length() < mappedPath.length())); } private boolean isBetterMethodMatch(RequestMappingInfo mapping, RequestMappingInfo mappingToCompare) { return (mappingToCompare.methods.length == 0 && mapping.methods.length > 0); } private boolean isBetterParamMatch(RequestMappingInfo mapping, RequestMappingInfo mappingToCompare) { return (mappingToCompare.params.length < mapping.params.length); } }
下面是俩个内部使用的工具方法
private String[] getMethodSecured(Method handlerMethod) { String[] secureds = this.methodPrivilegeCache.get(handlerMethod); if (secureds == null) { Secured s = handlerMethod.getAnnotation(Secured.class); if(s != null) { secureds = s.value(); this.methodPrivilegeCache.put(handlerMethod, secureds); } } return secureds; } private ServletHandlerMethodResolver getMethodResolver(Object handler) { Class handlerClass = ClassUtils.getUserClass(handler); ServletHandlerMethodResolver resolver = this.methodResolverCache.get(handlerClass); if (resolver == null) { resolver = new ServletHandlerMethodResolver(handlerClass); this.methodResolverCache.put(handlerClass, resolver); } return resolver; }
您还没有登录,请您登录后再发表评论
以上只是Spring Security学习过程中的一部分要点,实际上,这个框架非常深奥,包含了许多高级特性,如频道安全、密码存储、国际化的错误消息等。在学习时,建议结合实际项目实践,这样能更好地理解和掌握其工作原理...
在这个完整的项目实例中,我们将深入探讨Spring Security的核心概念以及如何将其应用于实际的Web应用程序开发。 首先,我们从用户、角色和权限这三个核心元素开始。在Spring Security中,用户信息通常存储在一个...
在压缩包文件`spring_gateway_security_webflux`中,可能包含了示例代码或配置文件,用于演示如何在Spring Cloud Gateway中集成Spring Security,实现统一登录认证鉴权。这些资源可以帮助开发者更快地理解和实践上述...
注解方式更加直观和简洁,例如`@Secured`、`@PreAuthorize` 和 `@PostAuthorize` 可以直接在方法上声明访问控制。 总结,SpringSecurity是一个功能强大的安全框架,它为开发者提供了安全Web应用的全套解决方案。...
在Spring Security的官方文档中,包含了详细的配置指南、API参考、示例代码和最佳实践,帮助开发者深入理解并有效使用这个框架。例如,5.1版本的新特性包括对Servlet和WebFlux的支持增强,以及与其他第三方库的集成...
在"spring security2.5 jar"中,包含了Spring Security框架的核心类和接口,这些类和接口定义了安全控制的基本机制。比如: 1. **认证**:这是验证用户身份的过程,Spring Security提供了多种认证方式,如基于表单...
在Spring Security 3版本中,它引入了许多改进和新特性,以适应不断变化的安全需求和挑战。 一、核心概念 1. **Filter Chain**: Spring Security 的核心在于其过滤器链,它拦截HTTP请求并执行相应的安全处理。过滤...
在本文中,我们将深入探讨Spring Security 3.1的主要特性和用法。 1. **身份验证**:Spring Security 提供了多种身份验证机制,包括基于内存的、JDBC的、LDAP的和自定义的。在3.1版本中,你可以配置`...
在SpringBoot Web开发中,SpringSecurity扮演着核心角色,负责处理身份验证、授权以及访问控制等方面的安全需求。狂神(秦疆)的教程以SpringBoot为基础,深入讲解了如何集成和使用SpringSecurity来构建安全的Web...
通过在Spring配置文件中定义`<http>`、`<authentication-manager>`等元素,或使用`@EnableGlobalAuthentication`、`@Secured`等注解,可以方便地配置安全策略。 4. **spring-security-ldap-3.1.3.RELEASE.jar**:这...
4. **访问控制表达式 (ACE) / 额外的安全注解**: Spring Security 提供了基于注解的安全性,允许开发者使用`@Secured`或`@PreAuthorize`、`@PostAuthorize`等注解来声明性地指定访问控制规则。 5. **会话管理**: ...
可能包含的内容有:SpringSecurity的架构设计、AOP(面向切面编程)在安全中的应用、基于角色的访问控制(Role-Based Access Control, RBAC)、OAuth支持、CSRF(跨站请求伪造)防护、以及如何与其他Spring模块如...
在本文中,我们将深入探讨Spring Security的配置及其在实际应用中的使用。 首先,Spring Security的核心概念包括用户、角色、权限和访问控制。它提供了一种机制来验证用户身份(身份验证),并决定用户是否可以访问...
接下来,Spring Security 3.1.3是3.1.x系列的一个维护版本,它在3.0.0的基础上做了进一步优化和bug修复,以提高稳定性和性能。这个版本的一些亮点包括: 1. **Remember Me服务增强**:提供了更多的选项来管理“记住...
- 使用`@Secured`或`@PreAuthorize`注解:在Controller方法上使用这些注解,根据方法级别的权限控制静态资源的访问。 4. **Web安全配置** Spring Security的配置通常在Java配置类中完成,通过`...
Spring Security 是一个强大的、高度可定制的身份验证和访问控制框架,广泛应用于Java EE平台上的安全解决方案。在本文中,我们将深入探讨如何在Spring Security 3中实现多用户登录功能。首先,我们需要理解Spring ...
Spring Security 是一个强大的、高度可定制的身份验证和访问控制框架,广泛用于Java应用程序的安全管理,尤其是在Spring生态体系中。"Spring Security 3 Demos" 是一套针对Spring Security 3 版本的示例项目,旨在...
Spring Security的访问控制基于角色,可以使用`@Secured`、`@PreAuthorize`、`@PostAuthorize`等注解进行细粒度控制。此外,`AccessDecisionManager`和`AccessDecisionVoter`可以用来定制复杂的决策流程。在提供的...
在Spring Security中,主要的注解包括`@EnableWebSecurity`、`@Configuration`、`@Autowired`、`@Override`、`@Secured`等。`@EnableWebSecurity`开启Web安全配置,它是Spring Security的核心注解,用于告诉Spring ...
在这个"Spring Security的例子"中,我们可以深入理解其核心概念和工作流程。 首先,Spring Security的核心组件包括: 1. **Filter Security Interceptor (FSI)**:这是Spring Security的Web安全部分,它通过一系列...
相关推荐
以上只是Spring Security学习过程中的一部分要点,实际上,这个框架非常深奥,包含了许多高级特性,如频道安全、密码存储、国际化的错误消息等。在学习时,建议结合实际项目实践,这样能更好地理解和掌握其工作原理...
在这个完整的项目实例中,我们将深入探讨Spring Security的核心概念以及如何将其应用于实际的Web应用程序开发。 首先,我们从用户、角色和权限这三个核心元素开始。在Spring Security中,用户信息通常存储在一个...
在压缩包文件`spring_gateway_security_webflux`中,可能包含了示例代码或配置文件,用于演示如何在Spring Cloud Gateway中集成Spring Security,实现统一登录认证鉴权。这些资源可以帮助开发者更快地理解和实践上述...
注解方式更加直观和简洁,例如`@Secured`、`@PreAuthorize` 和 `@PostAuthorize` 可以直接在方法上声明访问控制。 总结,SpringSecurity是一个功能强大的安全框架,它为开发者提供了安全Web应用的全套解决方案。...
在Spring Security的官方文档中,包含了详细的配置指南、API参考、示例代码和最佳实践,帮助开发者深入理解并有效使用这个框架。例如,5.1版本的新特性包括对Servlet和WebFlux的支持增强,以及与其他第三方库的集成...
在"spring security2.5 jar"中,包含了Spring Security框架的核心类和接口,这些类和接口定义了安全控制的基本机制。比如: 1. **认证**:这是验证用户身份的过程,Spring Security提供了多种认证方式,如基于表单...
在Spring Security 3版本中,它引入了许多改进和新特性,以适应不断变化的安全需求和挑战。 一、核心概念 1. **Filter Chain**: Spring Security 的核心在于其过滤器链,它拦截HTTP请求并执行相应的安全处理。过滤...
在本文中,我们将深入探讨Spring Security 3.1的主要特性和用法。 1. **身份验证**:Spring Security 提供了多种身份验证机制,包括基于内存的、JDBC的、LDAP的和自定义的。在3.1版本中,你可以配置`...
在SpringBoot Web开发中,SpringSecurity扮演着核心角色,负责处理身份验证、授权以及访问控制等方面的安全需求。狂神(秦疆)的教程以SpringBoot为基础,深入讲解了如何集成和使用SpringSecurity来构建安全的Web...
通过在Spring配置文件中定义`<http>`、`<authentication-manager>`等元素,或使用`@EnableGlobalAuthentication`、`@Secured`等注解,可以方便地配置安全策略。 4. **spring-security-ldap-3.1.3.RELEASE.jar**:这...
4. **访问控制表达式 (ACE) / 额外的安全注解**: Spring Security 提供了基于注解的安全性,允许开发者使用`@Secured`或`@PreAuthorize`、`@PostAuthorize`等注解来声明性地指定访问控制规则。 5. **会话管理**: ...
可能包含的内容有:SpringSecurity的架构设计、AOP(面向切面编程)在安全中的应用、基于角色的访问控制(Role-Based Access Control, RBAC)、OAuth支持、CSRF(跨站请求伪造)防护、以及如何与其他Spring模块如...
在本文中,我们将深入探讨Spring Security的配置及其在实际应用中的使用。 首先,Spring Security的核心概念包括用户、角色、权限和访问控制。它提供了一种机制来验证用户身份(身份验证),并决定用户是否可以访问...
接下来,Spring Security 3.1.3是3.1.x系列的一个维护版本,它在3.0.0的基础上做了进一步优化和bug修复,以提高稳定性和性能。这个版本的一些亮点包括: 1. **Remember Me服务增强**:提供了更多的选项来管理“记住...
- 使用`@Secured`或`@PreAuthorize`注解:在Controller方法上使用这些注解,根据方法级别的权限控制静态资源的访问。 4. **Web安全配置** Spring Security的配置通常在Java配置类中完成,通过`...
Spring Security 是一个强大的、高度可定制的身份验证和访问控制框架,广泛应用于Java EE平台上的安全解决方案。在本文中,我们将深入探讨如何在Spring Security 3中实现多用户登录功能。首先,我们需要理解Spring ...
Spring Security 是一个强大的、高度可定制的身份验证和访问控制框架,广泛用于Java应用程序的安全管理,尤其是在Spring生态体系中。"Spring Security 3 Demos" 是一套针对Spring Security 3 版本的示例项目,旨在...
Spring Security的访问控制基于角色,可以使用`@Secured`、`@PreAuthorize`、`@PostAuthorize`等注解进行细粒度控制。此外,`AccessDecisionManager`和`AccessDecisionVoter`可以用来定制复杂的决策流程。在提供的...
在Spring Security中,主要的注解包括`@EnableWebSecurity`、`@Configuration`、`@Autowired`、`@Override`、`@Secured`等。`@EnableWebSecurity`开启Web安全配置,它是Spring Security的核心注解,用于告诉Spring ...
在这个"Spring Security的例子"中,我们可以深入理解其核心概念和工作流程。 首先,Spring Security的核心组件包括: 1. **Filter Security Interceptor (FSI)**:这是Spring Security的Web安全部分,它通过一系列...