Chinaunix首页 | 论坛 | 博客
  • 博客访问: 608612
  • 博文数量: 765
  • 博客积分: 40000
  • 博客等级: 大将
  • 技术积分: 5005
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-16 18:49
文章分类

全部博文(765)

文章存档

2011年(1)

2008年(764)

我的朋友

分类:

2008-10-16 18:56:19

    前一篇文章里介绍了Spring Security的一些基础知识,相信你对Spring Security的工作流程已经有了一定的了解,如果你同时在读源代码,那你应该可以认识的更深刻。在这篇文章里,我们将对Spring Security进行一些自定义的扩展,比如自定义实现UserDetailsService,保护业务方法以及如何对用户权限等信息进行动态的配置管理。

    一 自定义UserDetailsService实现

    UserDetailsService接口,这个接口中只定义了唯一的UserDetails loadUserByUsername(String username)方法,它通过用户名来获取整个UserDetails对象。

    前一篇文章已经介绍了系统提供的默认实现方式InMemoryDaoImpl,它从配置文件中读取用户的身份信息(用户名,密码等),如果你的客户想修改用户信息,就需要直接修改配置文件(你需要告诉用户配置文件的路径,应该在什么地方修改,如何把明文密码通过MD5加密以及如何重启等)。听起来是不是很费劲啊!

    在实际应用中,我们可能需要提供动态的方式来获取用户身份信息,最常用的莫过于数据库了,当然也可以是LDAP等。本文首先介绍系统提供的一个默认实现类JdbcDaoImpl(org.springframework.security.userdetails.jdbc. JdbcDaoImpl),它通过用户名从数据库中获取用户身份信息,修改配置文件,将userDetailsService Bean的配置修改如下:

1 <bean id="userDetailsService"
2 class="org.springframework.security.userdetails.jdbc.JdbcDaoImpl"
3 p:dataSource-ref="dataSource"
4 p:usersByUsernameQuery="select userName, passWord, enabled, from users where userName=?"
5 p:authoritiesByUsernameQuery="select 
6 u.userName,r.roleName from users u,roles 
7 r,users_roles ur where u.userId=ur.userId and 
8 r.roleId=ur.roleId and u.userName=?"/>

    JdbcDaoImpl类继承自Spring Framework的JdbcDaoSupport类并实现了UserDetailsService接口,因为从数据库中读取信息,所以首先需要一个数据源对象,这里不在多说,这里需要重点介绍的是usersByUsernameQuery和authoritiesByUsernameQuery,属性,它们的值都是一条SQL语句,JdbcDaoImpl类通过SQL从数据库中检索相应的信息,usersByUsernameQuery属性定义了通过用户名检索用户信息的SQL语句,包括用户名,密码以及用户是否可用,authoritiesByUsernameQuery属性定义了通过用户名检索用户权限信息的SQL语句,这两个属性都引用一个MappingSqlQuery(请参考Spring Framework相关资料)实例,MappingSqlQuery的mapRow()方法将一个ResultSet(结果集)中的字段映射为一个领域对象,Spring Security为我们提供了默认的数据库表,如下图所示(摘自《Spring in Action》):

    图<!——[if supportFields]——>1<!——[if supportFields]——> JdbcDaoImp数据库表

    如果我们需要获取用户的其它信息就需要自己来扩展系统的默认实现,首先应该了解一下UserDetailsService实现的原理,还是要回到源代码,以下是JdbcDaoImpl类的部分代码:

 1 private class UsersByUsernameMapping extends MappingSqlQuery {
 2 
 3      protected UsersByUsernameMapping(DataSource ds) {
 4 
 5             super(ds, usersByUsernameQuery);
 6 
 7             declareParameter(new SqlParameter(Types.VARCHAR));
 8 
 9             compile();
10 
11      }
12 
13      protected Object mapRow(ResultSet rs, int rownum) throws SQLException {
14 
15             String username = rs.getString(1);
16 
17             String password = rs.getString(2);
18 
19             boolean enabled = rs.getBoolean(3);
20 
21             UserDetails user = new User(username, password, enabled, true,
22 
23                truetruenew GrantedAuthority[] {new GrantedAuthorityImpl("HOLDER")});
24 
25             return user;
26      }
27 
28 }

    也许你已经看出什么来了,对了,系统返回的UserDetails对象就是从这里来的,这就是读源代码的好处,DaoAuthenticationProvider提供者通过调用自己的authenticate(Authentication authentication)方法将用户在登录页面输入的用户信息与这里从数据库获取的用户信息进行匹配,如果匹配成功则将用户的权限信息赋给Authentication对象并将其存放在SecurityContext中,供其它请求使用。

[1]       

【责编:Chuan】

--------------------next---------------------

阅读(207) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~