16、Spring MVC 之 Web Security
来源:互联网 发布:淘宝店铺被永久查封 编辑:程序博客网 时间:2024/06/14 06:19
Spring Security是一个单独的项目,它可以无缝的和Spring MVC集成。Spring Security提供会特性保护web应用来自恶意的攻击。具体可以参看Spring Security的参考文档的章节,例如“CSRF protection”,“Security Response Headers”和“Spring MVC Integration”.注意:使用Spring Security去保护应用不是针对所有的特性。例如CSRF保护可以通过简单的添加CsrfFilter以及CsrfRequestDataValueProcessor来保护你的应用。可以查看Spring MVC Showcase做为一个例子。
另外一个选择是使用专门针对Web安全的框架,HDIV就是这样的一个框架并且可以和Spring MVC集成。
其实上面就是Spring官网对于Spring关于Web Security的介绍。如果就这样我觉得东西太少了。但是如果叫我详细的来解释一下Spring Security那么东西又太多了。那么我就针对一下Spring Security的里面的概念,以及它的入口还有它的源码来给大家讲一下Spring Security是如何做到Web Security的。
1、Spring Security Overview
下面是Spring Security官方的一个关于它的架构图。
下面来介绍一下主要的概念: AbstractSecurityInterceptor
:是一个抽象类,实现安全对象的安全拦截,抽象了基于HTTP资源与方法资源的安全验证。 AuthenticationManager
:处理验证请求,相当于用户登录验证。 AccessDecisionManager
:访问投票管理器。相当于用户权限验证。 SecurityMetadataSource
:需要来实现,用于储存并且能够确定ConfigAttribute(用户配置的属性)可以适用于一个给定的安全对象调用。 RunAsManager
:创建一个临时的Authentication(验证)对象仅用来验证当前安全对象调用。 AfterInvocationManager
:评论安全对象调用返回的对象,能够修改返回的对象或者throw an AccessDeniedException. MethodSecurityInterceptor
:提供基于方法级别的验证。 AspectJMethodSecurityInterceptor
:AspectJ JoinPoint安全拦截,包装JoinPoint到MethodInvocation代理使得它能够兼容security只能够支持MethodInvocation基础架构类。 FilterSecurityInterceptor
:通过Filter的形式执行HTTP资源的安全处理。
2、Spring Security Entrance
这次我们主要是讲Spring Security关于HTTP资源的安全处理,根据官方文档,使用Spring Security第一件事就是需要在web.xml文件中添加下面的filter描述:
<filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class></filter><filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern></filter-mapping>
这个配置会提供一个钩子到Spring Security web基础设施中。DelegatingFilterProxy是Spring Framework类用于代理到一个Filter实现,它是被声明在你的application context的Spring bean中。在这种情况下,这个bean会被命名为”springSecurityFilterChain”,它是一个被命名空间创建内部的基础设施bean用于处理web安全。注意:你不能够使用你自定义的bean名称。一旦你添加这个到你的web.xml文件中,你就可以开始修改你的application context文件了。Web安全服务配置使用元素。
3、Spring Security Process
首先展示一下Spring Security处理时序图:
其实里面最重要还是beforeInvocation(),finallyInvocation(),afterInvocation().下面我们来具体分析一下这三个方法的代码。大家注意结合Spring Security Overview中的概念对比来看,就会清晰的认识到这个组件的真实意义了。
1)beforeInvocation
主要包括用户的验证与授权。
protected InterceptorStatusToken beforeInvocation(Object object) { Assert.notNull(object, "Object was null"); final boolean debug = logger.isDebugEnabled(); if (!getSecureObjectClass().isAssignableFrom(object.getClass())) { throw new IllegalArgumentException( "Security invocation attempted for object " + object.getClass().getName() + " but AbstractSecurityInterceptor only configured to support secure objects of type: " + getSecureObjectClass()); } // 1、获取用户资源(SecurityMetadataSource) Collection<ConfigAttribute> attributes = this.obtainSecurityMetadataSource() .getAttributes(object); if (attributes == null || attributes.isEmpty()) { if (rejectPublicInvocations) { throw new IllegalArgumentException( "Secure object invocation " + object + " was denied as public invocations are not allowed via this interceptor. " + "This indicates a configuration error because the " + "rejectPublicInvocations property is set to 'true'"); } if (debug) { logger.debug("Public object - authentication not attempted"); } publishEvent(new PublicInvocationEvent(object)); return null; // no further work post-invocation } if (debug) { logger.debug("Secure object: " + object + "; Attributes: " + attributes); } if (SecurityContextHolder.getContext().getAuthentication() == null) { credentialsNotFound(messages.getMessage( "AbstractSecurityInterceptor.authenticationNotFound", "An Authentication object was not found in the SecurityContext"), object, attributes); } // 2、用户登录验证(AuthenticationManager) Authentication authenticated = authenticateIfRequired(); // Attempt authorization try { // 3、用户授权验证(AccessDecisionManager) this.accessDecisionManager.decide(authenticated, object, attributes); } catch (AccessDeniedException accessDeniedException) { publishEvent(new AuthorizationFailureEvent(object, attributes, authenticated, accessDeniedException)); throw accessDeniedException; } if (debug) { logger.debug("Authorization successful"); } if (publishAuthorizationSuccess) { publishEvent(new AuthorizedEvent(object, attributes, authenticated)); } // 4、试图运行一个不同的用户(RunAsManager) Authentication runAs = this.runAsManager.buildRunAs(authenticated, object, attributes); if (runAs == null) { if (debug) { logger.debug("RunAsManager did not change Authentication object"); } // no further work post-invocation return new InterceptorStatusToken(SecurityContextHolder.getContext(), false, attributes, object); } else { if (debug) { logger.debug("Switching to RunAs Authentication: " + runAs); } SecurityContext origCtx = SecurityContextHolder.getContext(); SecurityContextHolder.setContext(SecurityContextHolder.createEmptyContext()); SecurityContextHolder.getContext().setAuthentication(runAs); // need to revert to token.Authenticated post-invocation return new InterceptorStatusToken(origCtx, true, attributes, object); }}
2)finallyInvocation
设置用户的SecurityContext信息。
protected void finallyInvocation(InterceptorStatusToken token) { if (token != null && token.isContextHolderRefreshRequired()) { if (logger.isDebugEnabled()) { logger.debug("Reverting to original Authentication: " + token.getSecurityContext().getAuthentication()); } // 设置SecurityContext信息 SecurityContextHolder.setContext(token.getSecurityContext()); }}
3)afterInvocation
授权的后置处理,评论安全对象调用返回的对象,能够修改返回的对象或者throw an AccessDeniedException.
protected Object afterInvocation(InterceptorStatusToken token, Object returnedObject) { if (token == null) { // public object return returnedObject; } finallyInvocation(token); // continue to clean in this method for passivity if (afterInvocationManager != null) { // Attempt after invocation handling try { // 后置处理(AfterInvocationManager) returnedObject = afterInvocationManager.decide(token.getSecurityContext().getAuthentication(), token.getSecureObject(), token.getAttributes(), returnedObject); } catch (AccessDeniedException accessDeniedException) { AuthorizationFailureEvent event = new AuthorizationFailureEvent(token.getSecureObject(), token .getAttributes(), token.getSecurityContext().getAuthentication(), accessDeniedException); publishEvent(event); throw accessDeniedException; } } return returnedObject;}
通过这三个主要的方法是不是把Spring Security当中的组件都组合起来了。就能够达到用户验证与用户授权了。
官网地址:spring-framework-reference-4.2.6.RELEASE
- 16、Spring MVC 之 Web Security
- web项目学习之spring-security
- Spring Security Web Application 之 Security Filter Chain
- spring mvc 3 + security
- Spring之MVC web 框架
- Spring总结之Web MVC
- spring security整合spring mvc
- spring-security for spring mvc
- Spring 3之MVC & Security简单整合开发(一)
- Spring 3之MVC & Security简单整合开发(二)
- Spring 3之MVC & Security简单整合开发(三)
- Spring 3之MVC & Security简单整合开发(一)
- Spring 3之MVC & Security简单整合开发(二)
- Spring 3之MVC & Security简单整合开发(三)
- Spring 3之MVC & Security简单整合开发(一)
- Spring 3之MVC & Security简单整合开发(二)
- Spring 3之MVC & Security简单整合开发(三)
- Spring 3之MVC & Security简单整合开发(一)
- 【计算机】寻址方式
- LeetCode 231. Power of Two
- JAVA安装环境配置一
- 你不太熟悉的JVM命令配置参数
- ubuntu下 gstreamer 的配置及播放音视频例子(已经验证)
- 16、Spring MVC 之 Web Security
- mongoDB学习(1)介绍
- sql server获取当前月的天数
- Java NIO使用和总结
- 告诉你 Ubuntu 也可以这么玩
- 类和对象
- Ubuntu16.04下为pycharm 添加启动项
- 当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法
- 洛谷P3398 仓鼠找sugar