`

spring security 配置文件小结(2)

阅读更多
#  六、为了使用MD5对密码加密,我们需要修改一下配置文件。  
# 任何一个正式的企业应用中,都不会在数据库中使用明文来保存密码的,我们在之前的章节中都是为了方便起见没有对数据库中的用户密码进行加密,这在实际应用中是极为幼稚的做法。可以想象一下,只要有人进入数据库就可以看到所有人的密码,这是一件多么恐怖的事情,为此我们至少要对密码进行加密,这样即使数据库被攻破,也可以保证用户密码的安全。  
# 最常用的方法是使用MD5算法对密码进行摘要加密,这是一种单项加密手段,无法通过加密后的结果反推回原来的密码明文。  
#   
# <authentication-provider>  
#     <password-encoder hash="md5"/>  
#     <jdbc-user-service data-source-ref="dataSource"/>  
# </authentication-provider>  
#           
# 盐值加密  
# <authentication-provider>  
#     <password-encoder hash="md5">  
#         <salt-source user-property="username"/>  
#     </password-encoder>  
#     <jdbc-user-service data-source-ref="dataSource"/>  
# </authentication-provider>  
#           
# 在password-encoder下添加了salt-source,并且指定使用username作为盐值。  
# 盐值的原理非常简单,就是先把密码和盐值指定的内容合并在一起,再使用md5对合并后的内容进行演算,这样一来,就算密码是一个很常见的字符串,再加上用户名,最后算出来的md5值就没那么容易猜出来了。因为攻击者不知道盐值的值,也很难反算出密码原文。  
#   
# 七、 用户信息缓存  
# 介于系统的用户信息并不会经常改变,因此使用缓存就成为了提升性能的一个非常好的选择。Spring Security内置的缓存实现是基于ehcache的,为了启用缓存功能,我们要在配置文件中添加相关的内容。  
#   
# <authentication-provider>  
#     <password-encoder hash="md5">  
#         <salt-source user-property="username"/>  
#     </password-encoder>  
#     <jdbc-user-service data-source-ref="dataSource" cache-ref="userCache"/>  
# </authentication-provider>  
#           
# 我们在jdbc-user-service部分添加了对userCache的引用,它将使用这个bean作为用户权限缓存的实现。对userCache的配置如下所示:  
#   
# <beans:bean id="userCache" class="org.springframework.security.providers.dao.cache.EhCacheBasedUserCache">  
#     <beans:property name="cache" ref="userEhCache"/>  
# </beans:bean>  
#   
# <beans:bean id="userEhCache" class="org.springframework.cache.ehcache.EhCacheFactoryBean">  
#     <beans:property name="cacheManager" ref="cacheManager"/>  
#     <beans:property name="cacheName" value="userCache"/>  
# </beans:bean>  
#   
# <beans:bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"/>  
#           
# EhCacheBasedUserCache 是Spring Security内置的缓存实现,它将为jdbc-user-service提供缓存功能。它所引用的userEhCache来自 spring提供的EhCacheFactoryBean和EhCacheManagerFactoryBean,对于userCache的缓存配置放在 ehcache.xml中:  
#   
# <ehcache>  
#     <diskStore path="java.io.tmpdir"/>  
#   
#     <defaultCache  
#         maxElementsInMemory="1000"  
#         eternal="false"  
#         timeToIdleSeconds="120"  
#         timeToLiveSeconds="120"  
#         overflowToDisk="true"  
#     />  
#   
#     <cache  
#         name="userCache"  
#         maxElementsInMemory="100"  
#         eternal="false"  
#         timeToIdleSeconds="600"  
#         timeToLiveSeconds="3600"  
#         overflowToDisk="true"  
#     />  
# </ehcache>  
#           
#  cache解释:  
#  内存中最多存放100个对象。  
#  不是永久缓存。   
#  最大空闲时间为600秒。  
#  最大活动时间为3600秒。  
#  如果内存对象溢出则保存到磁盘。  
#    
# 八、获取当前用户信息  
# 如果只是想从页面上显示当前登陆的用户名,可以直接使用Spring Security提供的taglib。  
#   
# <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>  
# <div>username : <sec:authentication property="name"/></div>  
#           
# 如果想在程序中获得当前登陆用户对应的对象。  
#   
# UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext()  
#     .getAuthentication()  
#     .getPrincipal();  
#           
# 如果想获得当前登陆用户所拥有的所有权限。  
#   
# GrantedAuthority[] authorities = userDetails.getAuthorities();  
#           
# 关于UserDetails是如何放到SecuirtyContext中去的,以及Spring Security所使用的TheadLocal模式,我们会在后面详细介绍。这里我们已经了解了如何获得当前登陆用户的信息。  
#   
# 九、自定义访问拒绝页面  
# 在我们的例子中,user用户是不能访问/admin.jsp页面的,当我们使用user用户登录系统之后,访问/admin.jsp时系统默认会返回403响应。  
# 如果我们希望自定义访问拒绝页面,只需要随便创建一个jsp页面,让后将这个页面的位置放到配置文件中。  
#   
# 下面创建一个accessDenied.jsp  
#   
# <%@ page contentType="text/html;charset=UTF-8"%>  
# <html>  
#   <head>  
#     <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  
#     <title>Access Denied</title>  
#     <style type="text/css">  
# div.error {  
#     width: 260px;  
#     border: 2px solid red;  
#     background-color: yellow;  
#     text-align: center;  
# }  
#     </style>  
#   </head>  
#   <body>  
#     <h1>Access Denied</h1>  
#     <hr>  
#     <div class="error">  
#       访问被拒绝<br>  
#       ${requestScope['SPRING_SECURITY_403_EXCEPTION'].message}  
#     </div>  
#     <hr>  
#   </body>  
# </html>  
#   
#       
# 下一步修改配置文件,添加自定义访问拒绝页面的地址。  
#   
# <http auto-config='true' access-denied-page="/accessDenied.jsp">  
#     <intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" />  
#     <intercept-url pattern="/**" access="ROLE_USER" />  
# </http>  
#       
# 十、动态管理资源结合自定义登录页面  
# 如果想将动态管理资源与自定义登录页面一起使用,最简单的办法就是在数据库中将登录页面对应的权限设置为IS_AUTHENTICATED_ANONYMOUSLY。  
#   
# 因此在数据库中添加一条资源信息。  
#   
# INSERT INTO RESC VALUES(1,'','URL','/login.jsp*',1,'')  
#       
# 这里的/login.jsp*就是我们自定义登录页面的地址。  
#   
# 然后为匿名用户添加一条角色信息:  
#   
# INSERT INTO ROLE VALUES(3,'IS_AUTHENTICATED_ANONYMOUSLY','anonymous')  
#       
# 最后为这两条记录进行关联即可。  
#   
# INSERT INTO RESC_ROLE VALUES(1,3)  
#       
# 这样就实现了将动态管理资源与自定义登录页面进行结合。  
#   
#   
# 十一、后登陆的将先登录的踢出系统 vs 后面的用户禁止登陆  
# 默认情况下,后登陆的用户会把先登录的用户踢出系统。  
# 想测试一下的话,先打开firefox使用user/user登陆系统,然后再打开ie使用user/user登陆系统。这时ie下的user用户会登陆成功,进入登陆成功页面。而firefox下的用户如何刷新页面,就会显示如下信息:  
# This session has been expired (possibly due to multiple concurrent logins being attempted as the same user).             
# 这是因为先登录的用户已经被强行踢出了系统,如果他再次使用user/user登陆,ie下的用户也会被踢出系统了。  
#   
#   
# 后面的用户禁止登陆  
# 如果不想让之前登录的用户被自动踢出系统,需要为concurrent-session-control设置一个参数。  
# <http auto-config='true'>  
#     <intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" />  
#     <intercept-url pattern="/**" access="ROLE_USER" />  
#     <concurrent-session-control exception-if-maximum-exceeded="true"/>  
# </http>  
#               
# 这个参数用来控制是否在会话数目超过最大限制时抛出异常,默认值是false,也就是不抛出异常,而是把之前的session都销毁掉,所以之前登陆的用户就会被踢出系统了。  
#   
# 现在我们把这个参数改为true,再使用同一个账号同时登陆一下系统,看看会发生什么现象。  
# 很好,现在只要有一个人使用user/user登陆过系统,其他人就不能再次登录了。这样可能出现一个问题,如果有人登陆的时候因为某些问题没有进行logout就退出了系统,那么他只能等到session过期自动销毁之后,才能再次登录系统。  
#   
# 十二、单点登录;略。  
#   
# 十三、为不同用户显示各自的登陆成功页面  
# 一个常见的需求是,普通用户登录之后显示普通用户的工作台,管理员登陆之后显示后台管理页面。这个功能可以使用taglib解决。  
# 其实只要在登录成功后的jsp页面中使用taglib判断当前用户拥有的权限进行跳转就可以。  
# <%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>  
# <sec:authorize ifAllGranted="ROLE_ADMIN">  
#   <%response.sendRedirect("admin.jsp");%>  
# </sec:authorize>  
# <sec:authorize ifNotGranted="ROLE_ADMIN">  
#   <%response.sendRedirect("user.jsp");%>  
# </sec:authorize>        
#  当用户拥有ROLE_ADMIN权限时,既跳转到admin.jsp显示管理后台。  
#  当用户没有ROLE_ADMIN权限时,既跳转到user.jsp显示普通用户工作台。  
# 这里我们只做最简单的判断,只区分当前用户是否为管理员。可以根据实际情况做更加复杂的跳转,当用户具有不同权限时,跳到对应的页面,甚至可以根据用户username跳转到各自的页面  
#   
# 十四、匿名登录  
# 匿名登录,即用户尚未登录系统,系统会为所有未登录的用户分配一个匿名用户,这个用户也拥有自己的权限,不过他是不能访问任何被保护资源的。  
#   
# 设置一个匿名用户的好处是,我们在进行权限判断时,可以保证SecurityContext中永远是存在着一个权限主体的,启用了匿名登录功能之后,我们所需要做的工作就是从SecurityContext中取出权限主体,然后对其拥有的权限进行校验,不需要每次去检验这个权限主体是否为空了。这样做的好处是我们永远认为请求的主体是拥有权限的,即便他没有登录,系统也会自动为他赋予未登录系统角色的权限,这样后面所有的安全组件都只需要在当前权限主体上进行处理,不用一次一次的判断当前权限主体是否存在。这就更容易保证系统中操作的一致性。  
#   
# 配置文件  
# 在配置文件中使用auto-config="true"就会启用匿名登录功能。在启用匿名登录之后,如果我们希望允许未登录就可以访问一些资源,可以在进行如下配置。  
#   
# <http auto-config='true'>  
#     <intercept-url pattern="/" access="IS_AUTHENTICATED_ANONYMOUSLY" />  
#     <intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" />  
#     <intercept-url pattern="/**" access="ROLE_USER" />  
# </http>  
#           
# 在access中指定IS_AUTHENTICATED_ANONYMOUSLY后,系统就知道此资源可以被匿名用户访问了。当未登录时访问系统的“/”,就会被自动赋以匿名用户的身份。我们可以使用taglib获得用户的权限主体信息。  
#   
# 这里的IS_AUTHENTICATED_ANONYMOUSLY将会交由AuthenticatedVoter处理,内部会依据AuthenticationTrustResolver判断当前登录的用户是否是匿名用户。  
#   
# <div>  
#   username : <sec:authentication property="name"/>  
#   |  
#   authorities: <sec:authentication property="authorities" var="authorities" scope="page"/>  
# <c:forEach items="${authorities}" var="authority">  
#   ${authority.authority}  
# </c:forEach>  
# </div>  
#           
# 当用户访问系统时,就会看到如下信息,这时他还没有进行登录。  
# 这里显示的是分配给所有未登录用户的一个默认用户名roleAnonyMous,拥有的权限是ROLE_ANONYMOUS。我们可以看到系统已经把匿名用户当做了一个合法有效的用户进行处理,可以获得它的用户名和拥有的权限,而不需判断SecurityContext中是否为空。  
#   
# 实际上,我们完全可以把匿名用户像一个正常用户那样进行配置,我们可以在配置文件中直接使用ROLE_ANONYMOUS指定它可以访问的资源。  
#   
# <http auto-config='true'>  
#     <intercept-url pattern="/" access="ROLE_ANONYMOUS" />  
#     <intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" />  
#     <intercept-url pattern="/**" access="ROLE_USER" />  
# </http>  
#           
# 不过,为了更明显的将匿名用户与系统中的其他用户区分开,我们推荐在配置时尽量使用IS_AUTHENTICATED_ANONYMOUSLY来指定匿名用户可以访问的资源。  
#   
#   
# 十五、使用JAAS机制  
# 可以在Spring Security中使用JAAS机制进行用户的身份认证。  
#   
# JAAS 即Java Authentication and Authorization Service,它是JDK自带的一套专门用于处理用户认证和授权的标准API,Spring Security中可以使用API作为AuthenticationProvider处理用户认证与授权。  
#   
# 配置文件中,我们使用JaasAuthenticationProvider作为AuthenticationProvider。  
#   
# <http>  
#     <intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" />  
#     <intercept-url pattern="/**" access="ROLE_USER" />  
#     <form-login/>  
#     <logout/>  
# </http>  
#   
# <beans:bean id="jaasAuthenticationProvider"  
#     class="org.springframework.security.providers.jaas.JaasAuthenticationProvider">  
#     <custom-authentication-provider/>  
#     <beans:property name="loginConfig" value="/WEB-INF/login.conf" />  
#     <beans:property name="loginContextName" value="JAASTest" />  
#     <beans:property name="callbackHandlers">  
#         <beans:list>  
#             <beans:bean class="org.springframework.security.providers.jaas.JaasNameCallbackHandler" />  
#             <beans:bean class="org.springframework.security.providers.jaas.JaasPasswordCallbackHandler" />  
#         </beans:list>  
#     </beans:property>  
#     <beans:property name="authorityGranters">  
#         <beans:list>  
#             <beans:bean class="com.family168.springsecuritybook.ch117.AuthorityGranterImpl" />  
#         </beans:list>  
#     </beans:property>  
# </beans:bean>  
#       
# 注意不能在http标签中使用auto-config="true"或是在http标签中包含rememberMe,因为rememberMe需要引用userDetailsService,而在使用 JaasAuthenticationProvider时,用户数据校验是交由LoginModule处理的,不会使用 userDetailsService,所以rememberMe会抛出异常。  
#   
# 我们将JAAS所需的配置文件放在/WEB-INF/login.config。  
#   
# JAASTest {  
#     com.family168.springsecuritybook.ch117.LoginModuleImpl required;  
# };  
#       
# 并在配置文件中指明使用JAASTest作为登陆上下文。  
#   
# <beans:property name="loginContextName" value="JAASTest" />  
#       
# 现在要创建LoginModuleImpl用来处理用户登录。  
# package com.family168.springsecuritybook.ch117;  
# public class LoginModuleImpl implements LoginModule {  
#   
#     private String password;  
#     private String user;  
#     private Subject subject;  
#   
#     public boolean abort() throws LoginException {  
#         return true;  
#     }  
#   
#     public boolean commit() throws LoginException {  
#         return true;  
#     }  
#   
#     public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {  
#         this.subject = subject;  
#   
#         try {  
#             TextInputCallback textCallback = new TextInputCallback("prompt");  
#             NameCallback nameCallback = new NameCallback("prompt");  
#             PasswordCallback passwordCallback = new PasswordCallback("prompt", false);  
#   
#             callbackHandler.handle(new Callback[] {textCallback, nameCallback, passwordCallback});  
#   
#             password = new String(passwordCallback.getPassword());  
#             user = nameCallback.getName();  
#         } catch (Exception e) {  
#             throw new RuntimeException(e);  
#         }  
#     }  
#   
#     public boolean login() throws LoginException {  
#         if (!user.equals("user")) {  
#             throw new LoginException("Bad User");  
#         }  
#   
#         if (!password.equals("user")) {  
#             throw new LoginException("Bad Password");  
#         }  
#   
#         subject.getPrincipals().add(new Principal() {  
#                 public String getName() {  
#                     return "TEST_PRINCIPAL";  
#                 }  
#             });  
#   
#         subject.getPrincipals().add(new Principal() {  
#                 public String getName() {  
#                     return "NULL_PRINCIPAL";  
#                 }  
#             });  
#   
#         return true;  
#     }  
#   
#     public boolean logout() throws LoginException {  
#         return true;  
#     }  
# }  
#       
# 当用户登录成功时,会通过authorityGranters为权限主体授权,这一步也要自己实现AuthorityGranter接口。  
#   
#   
# package com.family168.springsecuritybook.ch117;  
#   
# import java.security.Principal;  
# import java.util.HashSet;  
# import java.util.Set;  
# import org.springframework.security.providers.jaas.AuthorityGranter;  
#   
# public class AuthorityGranterImpl implements AuthorityGranter {  
#     public Set grant(Principal principal) {  
#         Set rtnSet = new HashSet();  
#   
#         if (principal.getName().equals("TEST_PRINCIPAL")) {  
#             rtnSet.add("ROLE_USER");  
#             rtnSet.add("ROLE_ADMIN");  
#         }  
#   
#         return rtnSet;  
#     }  
# }  
#       
# 至此,JAAS与Spring Security结合进行认证授权的功能已经完成,每一步都要件功能写死在代码里,让人感觉很不舒服。  
#   
#    
#   
# 十六、保存登录之前的请求  
# 经常会碰到一种情况,用户花费大量时间编辑信息,但是session超时失效导致用户自动退出系统,安全过滤器会强制用户再次登录,但这也会使用户提交的信息全部丢失。  
#   
# 为了解决这个问题,Spring Security提供了一种称作SavedRequest功能,可以在未登录用户访问资源时,将用户请求保存起来,当用户登录成功之后SecurityContextHolderAwareRequestFilter会使用之前保存的请求,结合当前用户的请求生成一个新的请求对象,而这个请求对象中就保存了用户登录之前提交的信息。  
#   
# SavedRequest功能默认就会被Spring Security启用,不需任何配置就可以重用登陆之前请求提交的数据。  
#   
 
分享到:
评论

相关推荐

    spring security 配置文件小结(逐步深化到url级别)

    NULL 博文链接:https://whp0731.iteye.com/blog/453796

    Spring攻略PDF版

     1.5 使用配置文件配置容器   1.5.1 问题描述   1.5.2 解决方案   1.5.3 实现方法   1.6 小结   第2章 Spring简介   2.1 Spring Framework   2.1.1 Spring的模块介绍   2.1.2 ...

    Spring攻略中文版PDF

     1.5 使用配置文件配置容器   1.5.1 问题描述   1.5.2 解决方案   1.5.3 实现方法   1.6 小结   第2章 Spring简介   2.1 Spring Framework   2.1.1 Spring的模块介绍   2.1.2 ...

    Spring攻略英文版(附带源码)

     1.5 使用配置文件配置容器   1.5.1 问题描述   1.5.2 解决方案   1.5.3 实现方法   1.6 小结   第2章 Spring简介   2.1 Spring Framework   2.1.1 Spring的模块介绍   2.1.2 Spring的...

    Spring Security3 张卫滨(译)

    实现Spring Security的XML配置文件.......................................................................... 19 添加Spring DelegatingFilterProxy到web.xml文件...............................................

    Spring in Action(第2版)中文版

    目录 第一部分spring的核心 第1章开始spring之旅 1.1spring是什么 1.2开始spring之旅 1.3理解依赖注入 ...1.5小结 ...第2章基本bean装配 ...2.6小结 ...3.5.3配置属性的外在化 ...3.7小结 ...4.6小结 ...b.4小结

    Spring攻略(第二版 中文高清版).part2

    第5章 Spring Security 164 5.1 加强URL访问安全 165 5.1.1 问题 165 5.1.2 解决方案 165 5.1.3 工作原理 166 5.2 登录到Web应用 175 5.2.1 问题 175 5.2.2 解决方案 175 5.2.3 工作原理 175 5.3...

    Spring攻略(第二版 中文高清版).part1

    第5章 Spring Security 164 5.1 加强URL访问安全 165 5.1.1 问题 165 5.1.2 解决方案 165 5.1.3 工作原理 166 5.2 登录到Web应用 175 5.2.1 问题 175 5.2.2 解决方案 175 5.2.3 工作原理 175 5.3...

    Spring in Action(第二版 中文高清版).part2

    第一部分 Spring的核心 第1章 开始Spring之旅 1.1 Spring是什么 1.2 开始Spring之旅 1.3 理解依赖注入 1.3.1 依赖注入 1.3.2 DI应用 1.3.3 企业级应用中的依赖注入 1.4 应用AOP ...B.4 小结

    spring boot 全面的样例代码

    - [Spring Boot Actuator监控端点小结](http://blog.didispace.com/spring-boot-actuator-1/) - [在传统Spring应用中使用spring-boot-actuator模块提供监控端点]...

    Spring in Action(第二版 中文高清版).part1

    第一部分 Spring的核心 第1章 开始Spring之旅 1.1 Spring是什么 1.2 开始Spring之旅 1.3 理解依赖注入 1.3.1 依赖注入 1.3.2 DI应用 1.3.3 企业级应用中的依赖注入 1.4 应用AOP ...B.4 小结

    springboot学习

    chapter2-1-1:配置文件详解:自定义属性、随机数、多环境配置等 chapter2-1-2:2.0 新特性(一):配置绑定全解析 chapter2-2-1:2.0 新特性(二):新增事件ApplicationStartedEvent Web开发 chapter3-1-1:构建一...

    sales-order-system:Spring Web MVC + JPA + Hibernate + JSP + JSTL应用程序

    销售订单系统 项目不再得到积极维护,请参阅: 目录 概括 这是一个非常小的全栈Web应用程序,仅用作示例,仅用于演示...可以在Spring的application-security.xml配置文件中找到一些示例凭证。 运行单元测试 mvn test

    asp.net知识库

    C#静态成员和方法的学习小结 C#中结构与类的区别 C#中 const 和 readonly 的区别 利用自定义属性,定义枚举值的详细文本 Web标准和ASP.NET - 第一部分 XHTML介绍 在ASP.NET页面中推荐使用覆写(Override)而不是事件...

Global site tag (gtag.js) - Google Analytics