`
zzc1684
  • 浏览: 1223312 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

Spring security深入杂谈

阅读更多

spring security 是一个用于身份验证和访问控制的成熟框架,主要用于web的url访问,当然她也可以用于更加细粒度的访问控制(方法控制)但前者更具普遍意义,本文论述前者。
一 Quick start,一个简单的例子

step1: 在web.xml中添加spring security的代理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>

 step2: spring-security-context.xml

    <beans:beans xmlns="http://www.springframework.org/schema/security"
        xmlns:beans="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
          http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
          http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
    
        <http>
            <intercept-url pattern="/secure/extreme/**" access="ROLE_SUPERVISOR" />
            <intercept-url pattern="/secure/**" access="IS_AUTHENTICATED_FULLY" />
            <intercept-url pattern="/login.htm" access="IS_AUTHENTICATED_ANONYMOUSLY" />
            <intercept-url pattern="/images/*" filters="none" />
            <intercept-url pattern="/**" access="ROLE_USER" />
            <form-login login-page="/login.htm" default-target-url="/home.htm" />
            <logout logout-success-url="/logged_out.htm" />
        </http>
    
        <authentication-manager>
            <authentication-provider>
                <password-encoder hash="md5"/>
                <user-service>
                    <user name="bob" password="12b141f35d58b8b3a46eea65e6ac179e" authorities="ROLE_SUPERVISOR, ROLE_USER" />
                    <user name="sam" password="d1a5e26d0558c455d386085fad77d427" authorities="ROLE_USER" />
                </user-service>
            </authentication-provider>
        </authentication-manager>
 
    </beans:beans>

 好了,这是一个来自spring官网的例子,我们居然没写代码!好吧,我们看看这些配置都干了些什么.
首先是在web.xml中定义了一个名为:“springSecurityFilterChain”的过滤器。然后就是在spring的上下文文件中:
    <intercept-url pattern="/**" access="ROLE_USER" />
表示访问任何url的用户都必须拥有"ROLE_USER"的权限,而用户权限的定义是在
    <user name="bob" password="12b141f35d58b8b3a46eea65e6ac179e" authorities="ROLE_SUPERVISOR, ROLE_USER" />定义的。
仔细看看这些定义,你是不是觉得有点迷惑:
    <intercept-url pattern="/images/*" filters="none" />
表明对"/images/*"的访问是不需要任何权限的为什么"/**"又需要"ROLE_USER"的权限呢,对了,顺序很重要,url的权限判断是根据从上到下的顺序匹配第一个的。
    <form-login login-page="/login.htm" default-target-url="/home.htm" />
定义了登录页面“login-page”, 并且登录成功展示的页面“default-target-url”, 等等。
到这儿其实就是一个完整的spring security 的配置了,已经能够work了,是不是毫无成就感,这一切都是怎么发生的呢,一点都没展示!

好吧,我们开始抽丝剥茧,一点一点的讲明白这件事情。

 

 

二 这一切都是怎么发生的。
1. 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的保护是通过过滤器完成的,没错,就是你想到的那个“javax.servlet.Filter”。
这个名为“springSecurityFilterChain”    的filter会拦截所有的访问请求进行权限校验和访问控制。
“springSecurityFilterChain”是个代理,它将拦截到的请求委托给它代理的若干个filter进行校验。这些过滤器按照一定的顺序组成一个链对请求进行处理,这也体现在
代理的名字中“Chain”。这些filter的顺序和数量都是可配置的(在3.0中不可配置了,但是仍旧可以添加新的filter到任何位置),对这种 需求最好的解决方法就是依赖注入(IOC)可惜在web.xml中时没有IOC的,这就是为什么是个代理的原因:为了获取IOC的支持,所以真正的配置是 在spring的上下文中。
其实org.springframework.web.filter.DelegatingFilterProxy,这个类所代理的类是名为 springSecurityFilterChain的类,是在springcontext中定义的,在spring security3.0中这个类被框架自动创建了,是个 org.springframework.security.web.FilterChainProxy的instance。这一点在后面会另外讲。

2. spring-security-contect.xml

    <beans:beans xmlns="http://www.springframework.org/schema/security"
        xmlns:beans="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
          http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
          http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
    
        <http>
            <intercept-url pattern="/secure/extreme/**" access="ROLE_SUPERVISOR" />
            <intercept-url pattern="/secure/**" access="IS_AUTHENTICATED_FULLY" />
            <intercept-url pattern="/login.htm" access="IS_AUTHENTICATED_ANONYMOUSLY" />
            <intercept-url pattern="/images/*" filters="none" />
            <intercept-url pattern="/**" access="ROLE_USER" />
            <form-login login-page="/login.htm" default-target-url="/home.htm" />
            <logout logout-success-url="/logged_out.htm" />
        </http>
    
        <authentication-manager>
            <authentication-provider>
                <password-encoder hash="md5"/>
                <user-service>
                    <user name="bob" password="12b141f35d58b8b3a46eea65e6ac179e" authorities="ROLE_SUPERVISOR, ROLE_USER" />
                    <user name="sam" password="d1a5e26d0558c455d386085fad77d427" authorities="ROLE_USER" />
                </user-service>
            </authentication-provider>
        </authentication-manager>

 配置很简单,因为在spring security3.0中引入了命名空间,也就是说使用了命名空间框架就会帮你做大量的默认工作,好处就是配置简单,坏处就是细节
被掩盖了,你不明白为什么。呵呵。
按照之前的思路,在spring的上下文中应该有叫做:“springSecurityFilterChain”的类,它定义了很多的filter来处理请求,你想的没错,只是这个细节被
<http>这个标签掩盖了。
<http>的重要使命?
创建了filter链(被掩盖的细节终于出现了)

    <alias name="filterChainProxy" alias="springSecurityFilterChain"/>
    
    <bean id="filterChainProxy" class="org.springframework.security.web.FilterChainProxy">
        <sec:filter-chain-map path-type="ant">
            <sec:filter-chain pattern="/images/*" filters="none"/>
            <sec:filter-chain pattern="/**" filters="securityContextFilter, logoutFilter, formLoginFilter, requestCacheFilter,servletApiFilter, anonFilter, sessionMgmtFilter, exceptionTranslator, filterSecurityInterceptor" />
        </sec:filter-chain-map>
    </bean>

 <http>首先建立了"filterChainProxy"的bean并且为每一个url配上了默认的filter链,然后 将"filterChainProxy"起了个"springSecurityFilterChain"的别名,很眼熟吧,就是在web.xml中配置的 那个filter名。有一个来自spring官方网站的图可以清楚的看到<http>都内置了哪些filter:这些filter有的是可选 的,有的是必须的。

这些filter被<http>事先生成,并且顺序也是确定的。spring security不允许覆盖或者改变已经内置的filter,所以如果你想添加一些更加特殊化的处理只能在某个位置追加自己定义的filter,这一点 spring security是支持的。
在spring security中对web资源的保护共有17种过滤器,大部分一般都用不上,必须的有四种:
    1.HttpSessionIntegrationFilter: 记住用户信息。
    2.authenticationProcessingFilter: 配置用户登录页面,提示用户登录,并且对用户的身份进行验证,在该filter中有一个属性叫做                authenticationEntryPoint,这个bean中可以配置登录页面。
    3.exceptionTranslationFilter: 更友善的对用户展示异常。
    4.filterSecurityInterceptor: 根据用户所拥有的权限和资源所要求的权限进行最终的判定。
好了,到这里filter这件事情基本上讲完了,这些filter都干了些什么呢?

3. filter中都做了什么
在这个框架中,主要做了两件事情:用户验证和访问控制,需要做这两件事情的filter会注入authenticationManager(用户验证)和 accessDecsionManager(访问控制),先说authenticationManager,它负责用户验证,但是它本身不干活,把活派给 了authenticationProvider,spring security是个贴心的框架,本身提供了大量的provider供用户使用,如数据库认证,JAAS认证等等,
如果还没有适合的随时可以实现authentication provider去创建自己的provider。其实provider本身也不干活,它把活派发给了另外一个苦逼接口,UserDetailService,
它是真正的干活的,它有一个方法:public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException, DataAccessException{}
用来获取用户信息,如果信息存在则返回一个UserDetail对象,如果不存在则抛出UsernameNotFoundException。这个方法是需要用户自己实现的。如果验证成功,
provider 会生成一个Authentication对象并将这个对象放入 org.springframework.security.core.context.SecurityContext这个当前应用的安全上下文中,这 样的话当前应用在任何时候都可以获判断当前用户是否已经通过认证,以及获取当前用户的有关信息,如用户名,密码,权限等。
再说说accessDecsionManager,它负责判断当前用户是否有权限访问某个资源,它也不干活,派给了若干个 AccessDecisionVoter, 这些个接口负责投票,会有三种票:赞成,反对,弃权,而accessDecsionManager有三种不同的实现,分别实现了三种策略:只要有一个赞成 票就允许访问;只要大多数赞成就允许访问;都是赞成票才允许访问。这样就决定了一个用户是否有权访问一个资源。一般来说spring security提供了一个默认的实现:org.springframework.security.vote.RoleVoter就足以满足大多数的需 求了,这个类只要被访问的资源需要role_作为前缀的权限它就会通过比较user拥有的权限和资源需要的权限来进行投票,否则就投弃权票。知道了这个特 性就可以针对它来设置自己的用户权限和资源权限(使用role_作为前缀),一般没有必要自己实现。当然这个“role_”前缀的规则是可以通过设置来改 变的。

讲到这基本上都差不多了,说一个工作中的bug吧:
用户反映登录页面在出现异常情况时,如数据库down掉或者网络不通时总是报错:“该用户没有权限”,这个确实不妥。经过查找在 UserDetailService的实现类中方法loadUserByUsername中无论发生了任何异常都会catch而后抛出 UsernameNotFoundException,而在filter:AuthenticationProcessingFilter中如果一旦认证 失败,它会获取这个失败的异常并将这个exception写入session中,key值 为:“SPRING_SECURITY_LAST_EXCEPTION”,这样在jsp中就可以从session中获取这个exception,判断后告 诉用户到底是什么错误。无论什么错误只抛UsernameNotFoundException就导致jsp只看到这个异常也就只好老是报错“该用户没有权 限”了。改正的方法很简单,实现若干个继承了 org.springframework.security.core.AuthenticationException(UsernameNotFoundException 的父类)的异常,在catch到不同的错误时抛出然后在jsp中进行判断就可以了。

讲到这基本上都差不多了,最后再说一点,spring security提供了一个JSP标签库来方便在JSP页面中最安全信息进行获取。感兴趣可以自己看看,这里不详细说明了。

写的比较乱,错误之处请不吝指出,谢谢。

分享到:
评论

相关推荐

    SpringSecurity.pdf

    Spring Security是一个功能强大、高度定制的安全框架,它专门用于为基于Spring的应用程序提供安全性解决方案。Spring Security架构的设计初衷是为了解决认证和授权的需求,确保应用程序的安全性。它提供了全面的安全...

    安全框架Spring Security深入浅出视频教程

    视频详细讲解,需要的小伙伴自行网盘下载,链接见附件,永久有效。 首先,SSM环境中我们通过xml配置的...Springsecurity在两种不同的开发模式中使用,有经典的独立web后台管理系统,也有时下最流行的前后端分离场景。

    Spring Security in Action

    Spring Security 实践指南 Spring Security 是一个基于 Java 的安全框架,旨在提供身份验证、授权和访问控制等功能。下面是 Spring Security 的主要知识点: 一、身份验证(Authentication) 身份验证是指对用户...

    初识 Spring Security - v1.1.pdf

    ### 初识 Spring Security #### 一、Spring Security 概述 **Spring Security**是一种广泛应用于Java企业级项目中的安全框架,它基于Spring AOP(面向切面编程)和Servlet过滤器来提供全面的安全解决方案。该框架...

    Spring Security 资料合集

    这三份资料——"实战Spring Security 3.x.pdf"、"Spring Security 3.pdf" 和 "Spring Security使用手册.pdf" 将深入探讨这些概念,并提供实践指导,帮助读者掌握如何在实际项目中应用Spring Security。通过学习这些...

    springsecurity学习笔记

    在"springsecurity学习笔记"中,你可能会涉及以下主题: - Spring Security的基本配置,包括web安全配置和全局安全配置。 - 如何自定义认证和授权流程,比如实现自定义的AuthenticationProvider和...

    Spring Security 3.pdf

    Spring Security 是一个强大的Java安全框架,专为Java和Spring生态系统设计,用于实现全面的身份验证、授权和服务级安全功能。在Spring Security 3版本中,它引入了许多改进和新特性,以适应不断变化的安全需求和...

    SpringSecurity学习总结源代码

    在本文中,我们将深入探讨SpringSecurity的核心概念、关键组件以及如何配置和使用这个框架。 首先,SpringSecurity的核心功能包括用户认证、权限授权、会话管理以及防止常见攻击。其中,用户认证涉及验证用户凭据,...

    spring security 完整项目实例

    在这个完整的项目实例中,我们将深入探讨Spring Security的核心概念以及如何将其应用于实际的Web应用程序开发。 首先,我们从用户、角色和权限这三个核心元素开始。在Spring Security中,用户信息通常存储在一个...

    Spring Cloud Gateway 整合 Spring Security 统一登录认证鉴权

    首先,让我们深入了解Spring Cloud Gateway。这是一个基于Spring Framework 5,Spring Boot 2 和 Project Reactor 的高性能API网关。它提供了动态路由,服务熔断,负载均衡,以及针对微服务的细粒度控制等功能。通过...

    SpringSecurity笔记,编程不良人笔记

    在本笔记中,我们将深入探讨SpringSecurity的核心概念、配置以及如何与SpringBoot结合使用。 1. **SpringSecurity核心概念** - **Filter Chain**: SpringSecurity通过一系列过滤器实现其安全功能,这些过滤器构成...

    spring security 官方文档

    在Spring Security的官方文档中,包含了详细的配置指南、API参考、示例代码和最佳实践,帮助开发者深入理解并有效使用这个框架。例如,5.1版本的新特性包括对Servlet和WebFlux的支持增强,以及与其他第三方库的集成...

    spring security 4.0.0所需jar包

    - `spring-security-core-4.0.0.CI-SNAPSHOT-sources.jar`:提供源代码,便于深入学习和调试。 - `spring-security-core-4.0.0.CI-SNAPSHOT.jar`:核心模块的主要库,包括安全性元数据、认证、授权和访问决策管理...

    spring spring security2.5 jar

    Spring Security是Spring生态体系中的一个核心组件,主要负责应用程序的安全性,包括认证和...理解并熟练掌握这个版本,有助于深入理解Spring Security的工作原理,并为升级到更高版本或使用其他安全框架打下坚实基础。

    SpringBoot+SpringSecurity处理Ajax登录请求问题(推荐)

    SpringBoot+SpringSecurity处理Ajax登录请求问题 SpringBoot+SpringSecurity处理Ajax登录请求问题是SpringBoot开发中的一個常见问题,本文将详细介绍如何使用SpringBoot+SpringSecurity处理Ajax登录请求问题。 ...

    最详细Spring Security学习资料(源码)

    Spring Security是一个功能强大且高度可定制的身份验证和授权框架,专门用于保护Java应用程序的安全性。它构建在Spring Framework基础之上,提供了全面的安全解决方案,包括身份验证、授权、攻击防护等功能。 Spring...

    spring security3 中文版本

    ### Spring Security 3.0.1 中文版知识点解析 #### 一、Spring Security 3.0.1 概览 ##### 1.1 Spring Security 是什么? Spring Security 是一个强大的、高度可定制的身份验证和访问控制框架。它提供了许多功能...

    spring-security 官方文档 中文版

    ### Spring Security 官方文档中文版重要知识点解析 #### 一、Spring Security 概述 **1.1 Spring Security 是什么?** Spring Security 是一款基于 Spring 框架的安全插件,提供了完整的安全性解决方案,包括...

    精彩:Spring Security 演讲PPT

    #### 五、深入Spring Security 1. **认证机制**: Spring Security 支持多种认证方式,如表单认证、HTTP基本认证、OAuth2等。开发者可以根据实际需求选择合适的认证策略。 2. **授权机制**: 提供了灵活的授权模型,...

    SpringBoot+SpringSecurity+WebSocket

    在IT行业中,SpringBoot、SpringSecurity和WebSocket是三个非常重要的技术组件,它们分别在应用程序开发、安全管理和实时通信方面发挥着关键作用。本项目结合这三个技术,构建了一个整合的示例,旨在展示如何在...

Global site tag (gtag.js) - Google Analytics