为了进一步加强用户体验,提供密码修改功能是必须的。因为密码修改功能更多的是应用在用户名和密码都存到数据库的,所以这里基于内存修改密码不会关注存储机制,更多的会关注security框架本身对这种方式的拓展的整体流程和设计。
security框架中提供了一个UserDetailService的实现类InMemoryDaoImpl的类来管理内存用户,它的内存凭证存储使用了一个Map来存储内存中的用户和所关联的UserDetails。而这个UserDetails的实现类,security已经封装好了——o.s.s.core.userDetails.User。
既然我们知道了是InMemoryDaoImpl来管理内存中的用户,那我们只需要对UserDetailService以及它的实现类InMemoryDaoImpl进行拓展就可以达到密码修改的功能了。
首先我们需要做的是拓展UserDetailService以及它的实现类InMemoryDaoImpl,拓展完成之后,我们就想办法把我们拓展后的类覆盖掉security框架中原有的处理类。
第一步,拓展UserDetailService和InMemoryDaoImpl:
UserDetailService拓展:我们需要一个修改密码的方法,而UserDetailService是不具有的,所以我们需要创建一个继承了UserDetailService的类IChangePassword:
package securityservice; import org.springframework.security.core.userdetails.UserDetailsService; //imports omitted public interface IChangePassword extends UserDetailsService{ void changePassword(String username,String password); }
InMemoryDaoImpl拓展:这里的拓展我们需要保留它之前的方法,而且要实现我们刚拓展的那个修改密码的方法,所以需要继承InMemoryDaoImpl和实现IChangePassword:
package securityDaoImpl; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.memory.InMemoryDaoImpl; import securityservice.IChangePassword; public class InMemoryChangePasswordDaoImpl extends InMemoryDaoImpl implements IChangePassword { public void changePassword(String username,String password) { //get the UsrDetails User userDetails=(User)getUserMap().getUser(username); //creat a new UserDetails with the new password User newUserDetails=new User(userDetails.getUsername(),password,userDetails.isEnabled(),userDetails.isAccountNonExpired(),userDetails.isCredentialsNonExpired(),userDetails.isAccountNonLocked(),userDetails.getAuthorities()); //add to the map getUserMap().addUser(newUserDetails); } }
我们可以看到上面的实现代码,它从存储集合Map里面拿到当前的那个UserDetails凭证,然后创建一个新的UserDetails,修改了密码,然后保存到Map里,覆盖掉之前那个。
这里的拓展代码并不难实现,最主要的是理解它的整个处理流程和设计。
现在已经拓展完了,下一步需要把我们拓展好的类放到security框架中,覆盖掉原有的那个,这需要从配置文件里下手。ps:(这里可能由于每个人的命名空间的不同,所以配置文件的标签会有不一样,不过这并不影响。)
第二步:配置拓展后的UserDetailService到security框架中:
security有提供配置自定义UserDetailService的方法:
<authentication-manager alias="authenticationManager"> <authentication-provider user-service-ref="InMemoryChangePasswordDaoImpl"> </authentication-provider>
如上面代码显示,user-service-ref这个属性就是为了方便开发工程中拓展UserDetailService所提供的。
现在已经将其配置到security里面了,下一步要在配置文件初始化这个bean:
<beans:bean id="InMemoryChangePasswordDaoImpl" class="securityDaoImpl.InMemoryChangePasswordDaoImpl"> <beans:property name="userProperties"> <beans:props> <beans:prop key="guest">guest,ROLE_USER</beans:prop> </beans:props> </beans:property> </beans:bean>
到这一步,基于内存修改密码的功能已经拓展完了,剩下的工作只需要在controller里面调用这个改密的方法就ok了,下面是笔者本人的controller代码(只供参考):
package controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import securityservice.IChangePassword; @Controller public class ChangePasswordController { @Autowired private IChangePassword iChangePasswordDao; @RequestMapping(value="/changePassword",method=RequestMethod.POST) public String changePassword(@RequestParam("newPassword") String newpassword,@RequestParam("oldPassword") String oldpassword) { Object principal =SecurityContextHolder.getContext().getAuthentication().getPrincipal(); String username=principal.toString(); if(principal instanceof UserDetails) { username=((UserDetails)principal).getUsername(); } // if(((UserDetails)principal).getPassword().equals(oldpassword)) // { iChangePasswordDao.changePassword(username, newpassword); // } return "redirect:home.jsp"; } }
到这里,整个后台过程已经拓展完了,其实这里的拓展并不难,主要还是要理解其整体的处理流程和设计方法,然后按照security框架作者的设计思想去拓展,然后就可以水到渠成了。
本文是笔者学习经验所得,仅供参考,希望能帮到有需要的人。
相关推荐
SpringBoot+SpringSecurity+JWT+MybatisPlus实现基于注解的权限验证,可根据注解的格式不同,做到角色权限控制,角色加资源权限控制等,粒度比较细化。 @PreAuthorize("hasAnyRole('ADMIN','USER')"):具有admin或...
spring security 基于oauth 2.0 实现 sso 单点登录Demo 使用 spring security 基于oauth 2.0 实现 sso 单点登录Demo spring boot + spring security + spring security oauth
该资源是springsecurity+oauth2+jwt实现的单点登录demo,模式为授权码模式,实现自定义登录页面和自定义授权页面。应用数据存在内存中或者存在数据库中(附带数据库表结构),token存储分为数据库或者Redis。demo...
主题: Spring Security —— 演讲者 张明星 1、Traditional Web App Security Dev 2、Spring Security 2.x Quick Start 3、Spring Security 2.x Overview 4、Dive Into Spring Security Authentication ...
java毕业设计——基于spring boot的音乐播放网站设计与实现(源码+数据库).zip java毕业设计——基于spring boot的音乐播放网站设计与实现(源码+数据库).zip java毕业设计——基于spring boot的音乐播放网站设计与...
基于spring security + oauth2 + jwt ,可优雅集成第三方登录.zip
java毕业设计——基于spring boot的旅游网站设计与实现(源码+数据库).zip java毕业设计——基于spring boot的旅游网站设计与实现(源码+数据库).zip java毕业设计——基于spring boot的旅游网站设计与实现(源码+...
NULL 博文链接:https://clongjava.iteye.com/blog/1453648
上文我们利用Spring rmi实现了Spring的远程访问(Spring 实现远程访问详解——rmi),本文主要讲解利用HttpInvoke实现远程访问。 Spring httpInvoker使用标准java序列化机制,通过Http暴露业务服务。如果你的参数和...
此项目是采用springboot与springSecurity开发的人事管理系统,前端采用vue,是一个前后端分离的项目
SpringBoot+SpringSecurity整合示例代码,实现了从数据库中获取信息进行登录认证和权限认证。 本项目为idea工程,请用idea2019导入(老版应该也可以)。 本项目用户信息所需sql文件,在工程的resources文件夹下,...
java毕业设计——基于spring boot的在线选房网站设计与实现(源码+数据库).zip java毕业设计——基于spring boot的在线选房网站设计与实现(源码+数据库).zip java毕业设计——基于spring boot的在线选房网站设计与...
spring security spring security 中文文档
Spring Security三份资料,实战Spring Security 3.x.pdf;Spring Security 3.pdf;Spring Security使用手册.pdf
java毕业设计——基于spring boot的就业信息管理网站设计与实现(源码+数据库).zip java毕业设计——基于spring boot的就业信息管理网站设计与实现(源码+数据库).zip java毕业设计——基于spring boot的就业信息管理...
springboot+ spring security实现登录认证
java毕业设计——基于spring boot的理财管理网站设计与实现(源码+数据库).zip java毕业设计——基于spring boot的理财管理网站设计与实现(源码+数据库).zip java毕业设计——基于spring boot的理财管理网站设计与...
springSecurity 实现登陆验证、传参,包括源代码和MYSQL的建库脚本。 传参的功能可以实现记录登陆之前打开的页面,登陆之后自动跳转到之前打开的页面。
java毕业设计——基于spring boot的疫情数据查看网站设计与实现(源码+数据库).zip java毕业设计——基于spring boot的疫情数据查看网站设计与实现(源码+数据库).zip java毕业设计——基于spring boot的疫情数据查看...