`
lengyun3566
  • 浏览: 446594 次
  • 性别: Icon_minigender_1
  • 来自: 大连
博客专栏
D59180b9-02f1-3380-840c-ea34da46143c
《Spring Secur...
浏览量:379171
社区版块
存档分类
最新评论

《Spring Security3》第四章第一部分翻译下(自定义的UserDetailsService)

阅读更多

 

实现自定义的JDBC UserDetailsService

正如在前面章节中的那个练习,我们将以基本的JdbcDaoImpl作为起点,将其进行扩展以支持修改密码功能。

创建一个自定义的JDBC UserDetailsService

com.packtpub.springsecurity.security包下创建如下的类:

 

public class CustomJdbcDaoImpl extends JdbcDaoImpl implements 
IChangePassword {
  public void changePassword(String username, String password) {
    getJdbcTemplate() 
    update("UPDATE USERS SET PASSWORD = ? WHERE USERNAME = ?",
            password, username);
  }
}

 你可以看到这个类扩展了JdbcDaoImpl默认类,提供了按照用户请求更新数据库中密码的功能。我们使用标准的Spring JDBC模板完成这个功能。

 

为自定义的JDBC UserDetailsService添加Spring bean声明

dogstore-base.xml配置文件中,添加如下的Spring Bean声明:

 

<bean id="jdbcUserService" 
      class="com.packtpub.springsecurity.security.CustomJdbcDaoImpl">
  <property name="dataSource" ref="dataSource"/>
</bean>

 同样的,dataSource Bean引用指向了<embedded-database>声明,我们使用这个声明来安装HSQL内存数据库。

 

 

你会发现自定义的UserDetailsService允许我们与数据库直接交互。在接下来的例子中,我们将使用这个功能来扩展UserDetailsService的基本功能。在使用Spring Security的复杂应用中,这种类型的个性化是很常见的。

基于JDBC的内置用户管理

正如上面简单JdbcDaoImpl扩展所描述的那样,开发人员可能会扩展这个类,但同时也会保留基本的功能。而我们要实现更复杂功能时,如用户注册(online store所必须的)与用户管理功能、站点的管理员创建用户、更新密码等,又会怎样呢?

 

尽管这些功能借助JDBC语句都能相对容易的实现,但是Spring Security还是为我们提供了内置的功能以支持对数据库里的用户进行创建、读取、更新和删除的操作。这对简单的系统来说是很有用的,同时也为构建自定义需求的用户提供了很好的起点。

 

实现类o.s.s.provisioning.JdbcUserDetailsManager扩展了JdbcDaoImpl的功能,提供了一些很有用的与用户相关的方法,这些方法的一部分在o.s.s.provisioning.UserDetailsManager接口中进行了定义:

方法

描述

void createUser(UserDetails user)

根据给定的UserDetails创建一个新用户,并包含所有声明的GrantedAuthority

void updateUser(final UserDetails user)

根据给定的UserDetails更新一个用户。更新其GrantedAuthority并将其从用户缓存中清除。

void deleteUser(String username)

根据给定的用户名删除用户,并将其从用户缓存中清除。

boolean userExists(String username)

根据给定的用户名判断用户是否存在(不管是否可用)。

void changePassword(String oldPassword, String newPassword)

修改当期登录用户的密码。为了使得操作成功,用户必须提供正确的当期密码。

 

正如你所见,JdbcUserDetailsManagerchangePassword方法正好满足了我们CustomJdbcDaoImpl的不足——在修改之前,它会检验用户已存在密码。让我们看一下将CustomJdbcDaoImpl替换为JdbcUserDetailsManager需要怎样的配置步骤。

 

首先,我们需要在dogstore-base.xml中声明JdbcUserDetailsManager bean

 

<bean id="jdbcUserService" 
      class="org.springframework.security 
             .provisioning.JdbcUserDetailsManager">
  <property name="dataSource" ref="dataSource"/>
  <property name="authenticationManager" 
            ref="authenticationManager"/>
</bean>

 AuthenticationManager的引用要匹配我们之前dogstore-security.xml文件中声明的<authentication-manager>alias。不要忘记注释掉CustomJdbcDaoImpl的声明——我们暂时不会使用它。

 

 

接下来,我们需要对changePassword.jsp做一些小的调整:

 

<h1>Change Password</h1>
<form method="post">
  <label for="oldpassword">Old Password</label>:
  <input id="oldpassword" name="oldpassword" 
         size="20" maxlength="50" type="password"/>
  <br />
  <label for="password">New Password</label>:
  <input id="password" name="password" size="20" 
         maxlength="50" type="password"/>
  <br />

 

 最后,需要简单调整AccountController。将@Autowired引用IChangePassword的实现替换为:

 

@Autowired
private UserDetailsManager userDetailsManager;

 

 submitChangePasswordPage方法也会更加简单了,因为要依赖的当前用户信息将会由JdbcUserDetailsManager为我们确定:

 

public String submitChangePasswordPage(@RequestParam("oldpassword") 
       String oldPassword, 
  @RequestParam("password") String newPassword) {
  userDetailsManager.changePassword(oldPassword, newPassword);
  SecurityContextHolder.clearContext();
  return "redirect:home.do";
}

 在这些修改完成后,你可以重启应用并尝试新的修改密码功能。

 

注意当你没有提供正确的密码时将会发生什么。试想一下会发生什么?并尝试思考怎样调整能使得对用户更友好。

 

尽管我们没有阐述JdbcUserDetailsManager提供的所有功能,但是可以看出它能很容易与简单的JSP页面结合在一起(当然要进行适当授权)以允许管理员来管理站点的用户——这对产品级别的应用是必要的。

 

 

 

 

5
1
分享到:
评论
9 楼 601235723 2016-11-14  
bbjavaeye 写道
你好,有个问题请教一下
我配了
<bean id="jdbcUserService"   
      class="org.springframework.security   
             .provisioning.JdbcUserDetailsManager"> 
  <property name="dataSource" ref="dataSource"/> 
  <property name="authenticationManager"   
            ref="authenticationManager"/> 
</bean>
然后在<authentication-manager alias="authenticationManager">  又引用了jdbcUserService造成了循环引用,这个你是怎么解决的

请问你循环引用的问题解决了吗?
8 楼 bay1ts 2015-10-21  
抱歉,我弄错了,希望大家不会 被我误导。自己实现的changepassword方法并没有应用,那段被注释掉了。使用的是security框架提供的方法,方法内有对应的处理机制。
bay1ts 写道
bay1ts 写道
请问如果在改密码时旧密码的输入是错误的,应该出现什么情况呢?

是不是会通过呢,因为已经更改了changepassword的实现,在实现内没有处理这种情况。

7 楼 bay1ts 2015-10-21  
bay1ts 写道
请问如果在改密码时旧密码的输入是错误的,应该出现什么情况呢?

是不是会通过呢,因为已经更改了changepassword的实现,在实现内没有处理这种情况。
6 楼 bay1ts 2015-10-21  
请问如果在改密码时旧密码的输入是错误的,应该出现什么情况呢?
5 楼 bay1ts 2015-10-21  
学习spring security非常不错的资料,谢谢了。
4 楼 9光光9 2014-09-29  
试了下可以实现功能,只是我用的是mysql数据库,
我不知道我这样配置对不对,两个地方都引用到了myDataSources
xml配置如下:
<http auto-config="true" use-expressions="true">
    <intercept-url pattern="/login.do" access="permitAll"/>
    <intercept-url pattern="/account/*.do" access="hasRole('ROLE_ADMIN')"/>
    <intercept-url pattern="/*" access="hasRole('ROLE_USER')"/>
    <form-login login-page="/login.do"/>
    <logout invalidate-session="true" logout-success-url="/" logout-url="/logout.do"/>
      
  </http>  
  <authentication-manager alias="authenticationManager">  
    <authentication-provider >
    	<jdbc-user-service data-source-ref="myDataSource" 
    		users-by-username-query="select username, password,enabled from users where username=?"
    		authorities-by-username-query="select a.username, a.authority from authorities a,users u 
    			where u.username = a.username and a.username=?"
    	/>  
    </authentication-provider>  
  </authentication-manager> 
	<beans:bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<beans:property name="driverClassName" value="com.mysql.jdbc.Driver"/>
	    <beans:property name="url" value="jdbc:mysql://127.0.0.1:3306/testdb"/>
	    <beans:property name="username" value="root"/>
	    <beans:property name="password" value="root"/>
	</beans:bean>
	
	<beans:bean id="jdbcUserService" 
		class="org.springframework.security.provisioning.JdbcUserDetailsManager">
		<beans:property name="dataSource" ref="myDataSource"/>
		<beans:property name="authenticationManager" ref="authenticationManager"/>
	</beans:bean>
3 楼 xiejx618 2012-03-25  
bbjavaeye 写道
你好,有个问题请教一下
我配了
<bean id="jdbcUserService"   
      class="org.springframework.security   
             .provisioning.JdbcUserDetailsManager"> 
  <property name="dataSource" ref="dataSource"/> 
  <property name="authenticationManager"   
            ref="authenticationManager"/> 
</bean>
然后在<authentication-manager alias="authenticationManager">  又引用了jdbcUserService造成了循环引用,这个你是怎么解决的

对于你说的循环引用,我不知是怎么回事,我启动tomcat发现没有bean userDetailsManager,所以造成注入
@Autowired 
private UserDetailsManager userDetailsManager;
失败。后来想想应该注入jdbcUserUservice,所以将@Autowired 改为@Resource(name="jdbcUserService")
发现一切很正常,功能正如书所说,改变密码后使用改变密码后的密码才能登录。
2 楼 bbjavaeye 2011-10-28  
你好,有个问题请教一下
我配了
<bean id="jdbcUserService"   
      class="org.springframework.security   
             .provisioning.JdbcUserDetailsManager"> 
  <property name="dataSource" ref="dataSource"/> 
  <property name="authenticationManager"   
            ref="authenticationManager"/> 
</bean>
然后在<authentication-manager alias="authenticationManager">  又引用了jdbcUserService造成了循环引用,这个你是怎么解决的
1 楼 lijingzhi 2011-07-20  
受益了,谢谢

相关推荐

Global site tag (gtag.js) - Google Analytics