`
kong0itey
  • 浏览: 306129 次
社区版块
存档分类
最新评论

《Spring Security3》第三章第四部分翻译(修改密码)(转载)

阅读更多

实现修改密码管理

现在我们将要对基于内存的 UserDetailsService 进行简单的扩展以使其支持用户修改密码。因为这个功能对用户名和密码存于数据库的场景更有用,所以基于 o.s.s.core.userdetails.memory.InMemoryDaoImpl 扩展的实现不会关注存储机制,而是关注框架对这种方式扩展的整体流程和设计。在第四章中,我们将通过将其转移到数据库后台存储来进一步扩展我们的基本功能。

扩展基于内存的凭证存储以支持修改密码

Spring Security 框架提供的 InMemoryDaoImpl 内存凭证存储使用了一个简单的 map 来存储用户名以及关联的 UserDetails InMemoryDaoImpl 使用的 UserDetails 实现类是 o.s.s.core.userdetails.User ,这个实现类将会在 Spring Security API 中还会看到。

 

这个扩展的设计有意的进行了简化并省略了一些重要的细节,如需要用户在修改密码前提供他们的旧密码。添加这些功能将作为练习留给读者。

InMemoryChangePasswordDaoImpl 扩展 InMemoryDaoImpl

我们要首先写自定义的类来扩展基本的 InMemoryDaoImpl ,并提供允许用户修改密码的方法。因为用户是不可改变的对象,所以我们 copy 已经存在的 User 对象,只是将密码替换为用户提交的值。在这里我们定义一个接口在后面的章节中将会重用,这个接口提供了修改密码功能的一个方法:

 

Java代码  收藏代码
  1. package  com.packtpub.springsecurity.security;  
  2. // imports omitted   
  3. public   interface  IChangePassword  extends  UserDetailsService {    
  4. void  changePassword(String username, String password);  
  5. }  

 以下的代码为基于内存的用户数据存储提供了修改密码功能:

 

Java代码  收藏代码
  1. package  com.packtpub.springsecurity.security;  
  2. public   class  InMemoryChangePasswordDaoImpl  extends  InMemoryDaoImpl   
  3. implements  IChangePassword {  
  4.   @Override   
  5.   public   void  changePassword(String username,   
  6.                 String password) {  
  7.     // get the UserDetails   
  8.     User userDetails =   
  9.         (User) getUserMap().getUser(username);  
  10.     // create a new UserDetails with the new password   
  11.     User newUserDetails =   
  12.         new  User(userDetails.getUsername(),password,  
  13.         userDetails.isEnabled(),   
  14.         userDetails.isAccountNonExpired(),  
  15.       userDetails.isCredentialsNonExpired(),  
  16.         userDetails.isAccountNonLocked(),  
  17.         userDetails.getAuthorities());  
  18.     // add to the map   
  19.     getUserMap().addUser(newUserDetails);  
  20.   }  
  21. }  

 比较幸运的是,只有一点代码就能将这个简单的功能加到自定义的子类中了。我们接下来看看添加自定义 UserDetailsService pet store 应用中会需要什么样的配置。

配置 Spring Security 来使用 InMemoryChangePasswordDaoImpl

现在,我们需要重新配置 Spring Security XML 配置文件以使用新的 UserDetailsService 实现。这可能比我们预想的要困难一些,因为 <user-service> 元素在 Spring Security 的处理过程中有特殊的处理。需要明确声明我们的自定义 bean 并移除我们先前声明的 <user-service> 元素。我们需要把:

 

Xml代码  收藏代码
  1. < authentication-manager   alias = "authenticationManager" >   
  2.   < authentication-provider >   
  3.     < user-service   id = "userService" >   
  4.       < user   authorities = "ROLE_USER"   name = "guest"   password = "guest" />   
  5.     </ user-service >   
  6.   </ authentication-provider >   
  7. </ authentication-manager >   

 修改为:

 

Xml代码  收藏代码
  1. < authentication-provider   user-service-ref = "userService" />   

 在这里我们看到的 user-service-ref 属性,引用的是一个 id userService Spring Bean 。所以在 dogstore-base.xml Spring Beans 配置文件中,声明了如下的 bean

 

Xml代码  收藏代码
  1. < bean   id = "userService"   class ="com.packtpub.springsecurity.security.  
  2. InMemoryChangePasswordDaoImpl">   
  3.   < property   name = "userProperties" >   
  4.     < props >   
  5.       < prop   key = "guest" > guest,ROLE_USER </ prop >   
  6.     </ props >   
  7.   </ property >   
  8. </ bean >   

 你可能会发现,这里声明用户的语法不如 <user-service> 包含的 <user> 元素更易读。遗憾的是, <user> 元素只能使用在默认的 InMemoryDaoImpl 实现类中,我们不能在自定义的 UserDetailsService 中使用了。在这里例子中,这个限制使得事情稍微复杂了一点,但是在实际中,没有人会愿意长期的将用户定义信息放在配置文件中。对于感兴趣的读者, Spring Security 3 参考文档中的 6.2 节详细描述了以逗号分隔的提供用户信息的语法。

【高效使用基于内存的 UserDetailsService 。有一个常见的场景使用基于内存的 UserDetailsService 和硬编码的用户列表,那就是编写安全组件的单元测试。编写单元测试的人员经常编码或配置最简单的场景来测试组件的功能。使用基于内存的 UserDetailsService 以及定义良好的用户和 GrantedAuthority 值为测试编写人员提供了很可控的测试环境。】

 

到现在,你可以重启 JBCP Pets 应用,应该没有任何的配置错误报告。我们将在这个练习的最后的两步中,完成 UI 的功能。

构建一个修改密码的页面

我们接下来将会建立一个允许用户修改密码的简单页面。



 这个页面将会通过一个简单的链接添加到“ My Account ”页面。首先,我们在 /account/home.jsp 文件中添加一个链接:

 

Html代码  收藏代码
  1. < p >   
  2.   Please find account functions below...  
  3. </ p >   
  4. < ul >   
  5.   < li > < a   href = "changePassword.do" > Change Password </ a > </ li >   
  6. </ ul >   

 接下来,在 /account/ changePassword.jsp 文件中建立“ Change Password ”页面本身:

 

Html代码  收藏代码
  1. <? xml   version = "1.0"   encoding = "ISO-8859-1"   ?>   
  2. < %@ page  language = "java"   contentType = "text/html; charset=ISO-8859-1"   
  3. pageEncoding = "ISO-8859-1" % >   
  4. < jsp:include   page = "../common/header.jsp" >   
  5.   < jsp:param   name = "pageTitle"   value = "Change Password" />   
  6. </ jsp:include >   
  7. < h1 > Change Password </ h1 >   
  8. < form   method = "post" >   
  9.   < label   for = "password" > New Password </ label > :  
  10.   < input   id = "password"   name = "password"   size = "20"   maxlength = "50"    
  11. type = "password" />   
  12.   < br   />   
  13.   < input   type = "submit"   value = "Change Password" />    
  14. </ form >   
  15. < jsp:include   page = "../common/footer.jsp" />   
 

 

最后我们还要添加基于 Spring MVC AccountController 来处理密码修改的请求(在前面的章节中我们没有介绍 AccountController ,它是账号信息主页的简单处理类)。

AccountController 添加修改密码的处理

我们需要将对自定义 UserDetailsService 的应用注入到 com.packtpub.springsecurity.web.controller.AccountController ,这样我们就能使用修改密码的功能了。 Spring @Autowired 注解实现了这一功能:

 

Java代码  收藏代码
  1. @Autowired   
  2. private  IChangePassword changePasswordDao;  

 两个接受请求的方法分别对应渲染 form 以及处理 POST 提交的 form 数据:

 

Java代码  收藏代码
  1. @RequestMapping (value="/account/changePassword.  
  2. do ",method=RequestMethod.GET)  
  3. public   void  showChangePasswordPage() {    
  4. }  
  5. @RequestMapping (value="/account/changePassword.  
  6. do ",method=RequestMethod.POST)  
  7. public  String submitChangePasswordPage( @RequestParam ( "password" )   
  8. String newPassword) {  
  9.   Object principal = SecurityContextHolder.getContext().  
  10. getAuthentication().getPrincipal();  
  11.   String username = principal.toString();  
  12.   if  (principal  instanceof  UserDetails) {  
  13. username = ((UserDetails)principal).getUsername();  
  14. }  
  15.   changePasswordDao.changePassword(username, newPassword);  
  16.   SecurityContextHolder.clearContext();  
  17.   return   "redirect:home.do" ;  
  18. }  

 完成这些配置后,重启应用,并在站点的“ My Account ”下找到“ Change Password ”功能。

练习笔记

比较精细的读者可能意识到这个修改密码的 form 相对于现实世界的应用来说太简单了。确实,很多的修改密码实现要复杂的多,并可能包含如下的功能:

l  密码确认——通过两个文本框,确保用户输入的密码是正确的;

l  旧密码确认——通过要求用户提供要修改的旧密码,增加安全性(这对使用 remember me 功能的场景特别重要);

l  密码规则校验——检查密码的复杂性以及密码是否安全。

 

你可能也会注意到当你使用这个功能的时,会被自动退出。这是因为 SecurityContextHolder.clearContext() 调用导致的,它会移除用户的 SecurityContext 并要求他们重新认证。在练习中,我们需要给用户做出提示或者找到方法让用户免于再次认证。

小结

在本章中,我们更细节的了解了认证用户的生命周期并对 JBCP Pet  Store 进行了结构性的修改。我们通过添加真正的登录和退出功能,进一步的满足了安全审计的要求,并提升了用户的体验。我们也学到了如下的技术:

l  配置并使用基于 Spring MVC 的自定义用户登录界面;

l  配置 Spring Security 的退出功能;

l  使用 remember me 功能;

l  通过记录 IP 地址,实现自定义的 remember me 功能;

l  实现修改密码功能;

l  自定义 UserDetailsService InMemoryDaoImpl

在第四章中,我们将会使用基于数据库的认证信息存储并学习怎样保证数据库中的密码和其他敏感数据的安全。

分享到:
评论

相关推荐

    Spring Security3中文文档

    文档的翻译者lengyun3566在博客中提到,他翻译了Spring Security3的文档,并在每篇文章的开头强调了版权信息,要求转载时必须注明出处。这表明了作者对知识产权的尊重以及对读者的责任感。 ### 第一章:Spring ...

    《Spring Security3》第四章第四部分翻译(Remember me后台存储和SSL)附前四章doc文件

    《Spring Security3》第四章第四部分主要探讨了Remember me服务的后台存储机制以及如何结合SSL(Secure Sockets Layer)来增强应用的安全性。这一部分的知识点涵盖了Spring Security中Remember me的功能,用户身份...

    spring security3 中文版本

    自此之后,Spring Security 成为了 Spring 生态系统中的一个重要组成部分,不断迭代更新,以适应不断变化的安全需求和技术发展。 ##### 1.3 发行版本号 Spring Security 3.0.1 是在 Spring Security 3.0 的基础上...

    Spring Security in Action

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

    Spring Security3

    ### Spring Security3 相关知识点概述 #### 第一章:一个不安全应用的剖析 **安全审计** - **目的**:识别系统中的安全隐患,并评估安全措施的有效性。 - **过程**:通过模拟攻击来测试系统的安全性,分析日志记录...

    springSecurity3中文文档

    第二章:springsecurity起步 第三章:增强用户体验 第四章:凭证安全存储 第五章:精确的访问控制 第六章:高级配置和扩展 第七章:访问控制列表(ACL) 第八章:对OpenID开放 第九章:LDAP目录服务 第十章:使用...

    Spring security oauth源码

    OAuth是一种授权协议,允许用户让第三方应用在不分享其密码的情况下,访问其存储在另一服务提供者的数据。OAuth 1.0a主要处理签名机制,而OAuth 2.0则简化了流程,提供了授权码、隐式、密码和客户端凭据四种授权类型...

    基于spring security + oauth2 + jwt ,可优雅集成第三方登录.zip

    本项目以"基于spring security + oauth2 + jwt,可优雅集成第三方登录"为主题,旨在提供一个能够无缝整合第三方登录系统的解决方案。 Spring Security是一个强大的安全框架,它为Java和Java EE应用程序提供了全面的...

    spring security第一个项目

    在“spring security第一个项目”中,我们将探讨如何搭建一个基础的Spring Security环境,实现用户登录验证以及权限控制。 首先,我们需要理解Spring Security的基本架构。它由四个主要组件组成:Filter Security ...

    Spring Security 文档

    在使用Spring Security的四种方法中,第三种方法是最为推荐的,因为它提供了最大的可扩展性和灵活性。通过数据库存储,可以方便地管理和维护用户、角色和权限,而自定义过滤器和接口实现则允许我们根据业务逻辑定制...

    Spring Security3 中文版 张卫滨 推荐

    根据给定的信息,我们可以从《Spring Security3 中文版》一书中提炼出多个重要的知识点,主要涉及Spring Security的基础概念、具体实现以及高级配置等方面。下面将详细解释每一部分的关键内容。 ### 第一章:一个不...

    springsecurity3.1.pdf

    标题:springsecurity3.1.pdf 描述:springsecurity3.1.pdf 标签:spring security3.1 部分内容:SpringSecurity Reference Documentation by Ben Alex and Luke Taylor 3.1.4.RELEASE **一、Spring Security 3.1...

    spring security oauth2.0 (讲义+代码)

    OAuth2.0 是一种授权框架,允许第三方应用在用户许可的情况下访问其受保护的资源,而无需共享用户凭证。本讲义结合代码将深入探讨如何利用Spring Security OAuth2.0 实现这一目标。 首先,OAuth2.0 有四个核心角色...

    spring security3中文文档

    ### Spring Security3中文文档知识点概览 #### 第一章:一个不安全应用的剖析 - **安全审计**:介绍如何通过安全审计来发现系统中的安全漏洞,并解释审计的重要性。 - **关于样例应用**:本章节以JBCPPets应用为例...

    SpringSecurity+OAuth2+JWT分布式权限控制.zip

    本项目“SpringSecurity+OAuth2+JWT分布式权限控制”旨在提供一个完整的解决方案,帮助开发者构建安全的、基于微服务的分布式应用程序。 Spring Security 是一个强大的和高度可定制的身份验证和授权框架,适用于...

    Spring Security笔记.rar

    2. **OAuth2集成**:Spring Security支持OAuth2协议,可以用于实现第三方登录(如Facebook、Google)。 3. **CSRF防护**:Spring Security提供跨站请求伪造(CSRF)防护机制,防止恶意攻击。 总的来说,Spring ...

    springsecurity入门实例

    3. **社交登录**:集成 OAuth2 或其他第三方登录服务,如 Google、Facebook,为用户提供便利。 在"TestSecurity"这个实例中,你将会看到一个简单的 Spring Security 配置和运行流程,包括登录、权限控制以及可能的...

    spring security从零学起

    4. OAuth2集成:Spring Security可以与OAuth2结合,实现第三方登录功能。 六、源码分析 深入理解Spring Security的源码有助于定制更复杂的解决方案。关键类如AbstractAuthenticationProcessingFilter、...

    自定义Spring Security的身份验证失败处理方法

    三、Spring Security 的 AuthenticationFailureHandler Spring Security 提供了一个默认的身份验证失败处理组件,但是,我们发现于默认行为不足以满足实际要求的情况是很常见的。如果是这种情况,我们可以创建自己...

Global site tag (gtag.js) - Google Analytics