知识点

相关文章

更多

最近更新

更多

《Spring Security 3》 【第四章】 凭证安全存储(5)

2019-03-14 12:56|来源: 开涛

将Remember me功能迁移至数据库

现在你可能会意识到我们remember me功能的实现,能够在应用重启前很好的使用,但在应用重启时用户的session会被丢失。这对用户来说会不太便利,他们不应该关心JBCP Pets的维护信息。


幸运的是,Spring Security提供了将rememberme token持久化到任何存储的接口o.s.s.web.authentication.rememberme.PersistentTokenRepository,并提供了这个接口的JDBC实现。


配置基于数据库的remember me tokens

在这里,修改remember me的配置以持久化到数据库是非常简单的。Spring Security配置的解析器能够识别出<remember-me>声明的data-source-ref新属性并为RememberMeServices切换实现类。让我们了解完成这个功能所需要的步骤。


添加SQL以创建remember me schema

我们需要将包含期望schema定义的SQL文件放在classpath下(WEB-INF/classes中),它会与我们在前面使用的其它启动SQL脚本放在一起。我们将这个SQL脚本命名为remember-me-schema.sql:

  1. create table persistent_logins (    

  2.  username varchar_ignorecase(50) not null,    

  3.  series varchar(64) primary key,    

  4.  token varchar(64) not null,    

  5.  last_used timestamp not null);    


为嵌入式数据库声明添加新的SQL脚本

接下来,在dogstore-security.xml文件的<embedded-database>声明中添加对新SQL脚本的引用:

  1. <jdbc:embedded-database id="dataSource" type="HSQL">    

  2.  <jdbc:script location="classpath:security-schema.sql"/>    

  3.  <jdbc:script location="classpath:remember-me-schema.sql"/>    

  4.  <jdbc:script location="classpath:test-users-groups-data.sql"/>    

  5. </jdbc:embedded-database>    


配置remember me服务持久化到数据库

最后我们需要对<remember-me>声明做一些简单的配置修改使其指向我们使用的data source:

  1. <http auto-config="true" use-expressions="true"    

  2.      access-decision-manager-ref="affirmativeBased">    

  3.  <intercept-url pattern="/login.do" access="permitAll"/>    

  4.  <intercept-url pattern="/account/*.do"      

  5.             access="hasRole('ROLE_USER') and fullyAuthenticated"/>    

  6.  <intercept-url pattern="/*" access="hasRole('ROLE_USER')"/>    

  7.  <form-login login-page="/login.do" />    

  8.  <remember-me key="jbcpPetStore" token-validity-seconds="3600"    

  9.               data-source-ref="dataSource"/>    

  10.  <logout invalidate-session="true" logout-success-url=""    

  11.          logout-url="/logout"/>    

  12. </http>    

这就是我们所有要做的。现在,如果你重启应用,将不会丢失之前合法用户设置的remember me cookie。


基于数据库后台的持久化tokens是不是更安全?

你可能会回忆起我们在第三章实现的TokenBasedRememberMeServices,它用MD5哈希算法将一系列与用户相关的数据编码成安全的cookie,这种方式很难(但并非不可能)篡改。o.s.s.web.authentication.rememberme.PersistentTokenBasedRememberMeServices类实现了持久化tokens以及对token安全处理,它通过一个校验方法以稍微不同的方式处理潜在的篡改。

PersistentTokenBasedRememberMeServices为每个用户创建一个唯一的序列号,用户在继续交互和认证时要使用序列号中唯一的tokens。序列号和token被存储在cookie中,在认证时要用来与存储的token进行对比。序列号和token都是基于配置的长度随机生成的,这使得恶意用户成功暴力破解的可能性很小了。

与TokenBasedRememberMeServices类似,持久化的token也可能被cookie窃取或其它的man-in-the-middle技术。在使用持久化token时,依旧建议用自定义的子类将IP地址合并到持久化token中,以及对站点的敏感区域强制使用用户名和密码认证。


用SSL保护你的站点

在日常使用在线站点时,你很可能已经听说或使用过SSL。安全套接字层(SSL)协议,以及其后续的传输层安全(TLS),被用来为网络上的HTTP事务提供传输层的安全——它们被称为安全的HTTP事务(HTTPS)。

简而言之,SSL和TLS以一种对用户透明的方式保护原始的HTTP传输数据,这些数据在客户端浏览器和web服务器之间传输。但是作为开发人员,在设计安全站点时,规划使用SSL是很重要的。Spring Security提供了一系列的配置选项可以灵活的将SSL集成到web应用中。

【尽管SSL和TLS是不同的协议(TLS是更成熟的协议),单数大多数人更熟悉SSL这个术语,所以在本书的剩余部分,我们使用这个术语来代指SSL和TLS两个协议。】

详细介绍SSL协议的机制已经超出了本书的范围,有一些很好的书籍和技术论文很详细地介绍了其规范和协议(你可以从RFC:5246:传输安全协议(TLS)Version1.2开始,在以下地址http://tools.ietf.org/html/rfc5246)


配置Apache Tomcat以支持SSL

首先且最重要的是,如果你计划执行如下SSL相关的例子,需要配置应用服务器以支持SSL连接。对于Apache Tomcat,这相对很容易。如果你在使用其它的应用服务器,请查看文档的相关部分。


生成server key store

我们需要使用Java的keytool命令来生成一个key store。打开一个命令提示窗口,并输入以下的命令:

  1. keytool -genkeypair -alias jbcpserver -keyalg RSA -validity 365   -keystore tomcat.keystore -storetype JKS    

按照提示进行如下的输入。输入密码password作为key store和个人密钥的密码。

  1. What is your first and last name?    

  2.  [Unknown]:  JBCP Pets Admin    

  3. What is the name of your organizational unit?    

  4.  [Unknown]:  JBCP Pets    

  5. What is the name of your organization?    

  6.  [Unknown]:  JBCP Pets    

  7. What is the name of your City or Locality?    

  8.  [Unknown]:  Anywhere    

  9. What is the name of your State or Province?    

  10.  [Unknown]:  NH    

  11. What is the two-letter country code for this unit?    

  12.  [Unknown]:  US    

  13. Is CN=JBCP Pets Admin, OU=JBCP Pets, O=JBCP Pets, L=Anywhere, ST=NH, C=US    

  14. correct?    

  15.  [no]:  yes    

这将会在当前目录下,生成一个名为tomcat.keystore的文件。这就是启用Tomcat SSL所使用的key store。

【注意的是要执行的是genkeypair命令(在早于java 6的释放版本中要使用keytool的genkey命令)】

为了下一步的操作,需要记住这个文件的地址。


配置Tomcat的SSL Connector

在Apache Tomcat的conf目录下,用XML编辑器(Eclipse或类似的都可以)打开server.xml,并取消注释或添加SSL Connector声明。应该如下所示:

  1. <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"    

  2.  maxThreads="150" scheme="https" secure="true"    

  3.  sslProtocol="TLS"    

  4.  keystoreFile="conf/tomcat.keystore"    

  5.  keystorePass="password"/>    

确保在上一步中生成的tomcat.keystore文件被copy到了Tomcat安装路径的conf目录下。在配置后,Tomcat服务器可以重启,JBCP  Pets应用能够在一个安全的端口https://localhost:8443/JBCPPets/上进行访问。

取决于不同的浏览器,可能需要包含https而不是http。这样的问题可能会比较难发现,你可能会比较奇怪为什么不能看到JBCP  Pets的主页。


对站点进行自动的安全保护

我们假设你在对客户的数据进行SSL保护时遇到了麻烦,你想把应用的特定部分置于SSL的保护之下。幸运的是,Spring Security让这一切变得很简单,只需要在<intercept-url>声明上添加一个配置属性。

requires-channel属性能够添加到任何<intercept-url>声明中,以要求所有匹配的URL要以特定的协议(HTTP,HTTPS或都可以)进行传递。如果按照这种形式来增强JBCP Pets站点,配置可能如下所示:

  1. <http auto-config="true" use-expressions="true">    

  2.  <intercept-url pattern="/login.do" access="permitAll"    

  3.                 requires-channel="https"/>    

  4.  <intercept-url pattern="/account/*.do"    

  5.                 access="hasRole('ROLE_USER') and fullyAuthenticated"    

  6.                 requires-channel="https"/>    

  7.  <intercept-url pattern="/*" access="permitAll"    

  8.                 requires-channel="any"/>    

  9.  <!-- ... -->    

  10. </http>      

如果此时重启应用,你将会发现:

 现在访问登录页和账号页需要HTTPS,浏览器将会为用户自动从不安全的(HTTP)URL重定向到安全的URL。例如,尝试访问http://localhost:8080/JBCPPets/login.do将会被定向到https://localhost:8443/JBCPPets/login.do

 如果用户被切换到了安全的HTTPS URL,如果他访问一个不必要使用HTTPS的URL,他能继续保留在HTTPS状态。

我们可以想象这种配置对于安全的好处——大多数的现代应用服务器使用一个secure标识session的cookie,所以强制要求登录页是安全的(如果这是应用的session被首次分配的地方)能够保证session的cookie能够被安全的传输,所以出现session劫持的可能性也更小。另外,直接将SSL加密配置在安全声明上的做法,能够很容易的保证应用中所有敏感的页面被适当和完整的保护。

为用户自动切换适当协议(HTTP或HTTPS)的功能,通过Spring Security过滤器链上的另外一个servlet过滤器来实现的(它的位置很靠前,在SecurityContextPersistenceFilter后面)。如果任何URL用requires-channel属性声明使用特定类型的协议,o.s.s.web.access.channel.ChannelProcessingFilter将会自动添加到过滤器链上

        ChannelProcessingFilter在请求时的交互过程如下图所示:



如果你的应用需要超出内置功能的复杂逻辑,ChannelProcessingFilter的设计可以进行扩展和增强。注意我们尽管只在图中说明了SecureChannelProcessor和RetryWithHttpsEntryPoint的实现,但是有类似的类去校验和处理声明为要求HTTP的URL。

注意,ChannelEntryPoint使用了HTTP 302的URL重写,这就不能使用这种技术去重定向POST的URL(尽管典型的POST请求不应该在安全协议和不安全协议间传递,因为大多数的应用都会对这种行为提出警告)。


安全的端口映射

在一些特定的环境中,可能不会使用标准的HTTP和HTTPS端口,其默认为80/443或8080/8443。在这种情况下,你必须配置你的应用包含明确的端口映射,这样ChannelEntryPoint的实现能够确定当重定向用户到安全或不安全的URL时,使用什么端口。

这仅需要增加额外的配置元素<port-mappings>,它能够指明除了默认的端口以外,额外的HTTP 的HTTPS端口:

  1. <port-mappings>    

  2.  <port-mapping http="9080" https="9443"/>    

  3. </port-mappings>  

 

如果你的应用服务器在反向代理后的话,端口映射将会更加的重要。

小结

在本章中,我们:

 介绍了把安全数据存储在支持JDBC的数据库中是如何配置的;

 配置JBCP Pets使用数据库来进行用户认证以及高安全性的密码存储,这里我们使用了密码加密和salting技术;

 管理JDBC持久化到数据中的用户;

 配置用户到安全组中。组被授予角色,而不是直接对用户进行角色的指定。这提高了站点和用户功能的可管理性;

 介绍了Spring Security使用遗留的(非默认的)数据库schema;

 讲解了HTTPS技术的配置及应用,它能够提高数据在访问应用敏感内容时的安全性。

在接下来的章节中,我们将会介绍Spring Security一些高级的授权功能,并引入Spring Security的JSP标签以实现良好的授权。


感谢  iteye  lengyun3566

他的博客地址:http://lengyun3566.iteye.com

他的新浪微博:http://weibo.com/1920428940

本书源代码的地址:http://www.packtpub.com/support?nid=4435


本文链接:领悟书生教程网,转自http://sishuok.com


相关问答

更多
  • 给你个下载地址,很全的: http://www.verycd.com/topics/93279/ 滚动屏幕找到你要的内容,自己下载吧
  • 继承就是从一个类衍生出一个新的类,新的类就具有原来的类的属性、方法,也可以再另外定义属性、方法; 举例来说,比如,人,具有身高、体重等属性,也具有吃饭、睡觉的方法,那衍生出一个类-女人,“女人”继承了“人”,所以女人也有身高体重、吃饭、睡觉,同时女人也可以有自己特有的东西,比如生孩子、哺乳等等。。。
  • 您要的答案我已发送,请按照步骤进行操作!! 你的采纳是我前进的动力, 记得好评和采纳,互相帮助,
  • spring
  • 一开始左边有有个蛋,按左他会停下来。1,连续的按左右,它会突然冲刺,在那一瞬间跳起来就行。(多试几次)。 2,再就是旋转的,你往左走他逆时针,往右顺时针,慢慢的进去,左右左右的出来,但要跳一下。有一块会掉。 4,之后是三个问号,不能随便跳,第一个问号。要把握好时间,让锯齿朝上并往又偏一点。因为左边还有一个问号是过关必备的,挡着了就拿不到了。也不要太下,因为你要跳过去。第二个问号是头 盔,吃了之后回去顶前面三个问号 5,先顶下面那个问号,掉下一个方块拿来垫脚,再移过去叠起来,再移过去顶最上面的,会有一个炸弹, ...
  • 通常,最好将问题分解为多个StackOverflow问题,因为您更有可能找到知道单个问题的答案的人。 我们如何避免为认证失败创建会话? 默认情况下,Spring Security会将最后一次未经身份验证的请求保存到会话中,以便在进行身份验证后可以再次自动发出请求。 例如,如果您在浏览器中请求example.com/a/b/c并且未通过身份验证,则它会将example.com/a/b/c保存到HttpSession中,然后让用户进行身份验证。 通过身份验证后,它会自动为您提供example.com/a/b/c ...
  • 经过一番研究,最终找到了解决方案。 需要在2 ADFS之间定义声明规则。 在声明提供程序ADFS中,您需要在依赖方信任中配置规则。 添加规则“将LDAP属性作为声明发送”和属性存储选择“Active Directory”LDAP属性选择“SAN-ACCOUNT-NAME”,传出声明选择“给定名称” 在资源方ADFS中,您需要在声明提供程序信任中配置规则。 添加规则“转换传入声明”。 并且传入的声明类型选择“给定名称”,传出声明类型选择“名称ID”,格式选择“未指定”您还需要在依赖方信任中配置规则。 添加规则 ...
  • 在身份验证期间,应用程序将引发以下错误: java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null" 抛出此异常,因为提供的(纯文本)密码缺少password-encoder {id} -prefix。 Spring Security 5现在使用以下格式存储密码(以前版本的spring security不是这种情况): {id}encodedPassword 这意味着对于纯文本密码, { ...
  • 您可以编写AbstractAuthenticationProcessingFilter的子类: 基于浏览器的基于HTTP的身份验证请求的抽象处理器。 并将此类添加到过滤器链,请参阅Spring Security Reference : 您可以使用custom-filter元素和其中一个名称将自己的过滤器添加到堆栈,以指定过滤器应显示的位置: