首先看代码:
- <authentication-manager alias="authenticationManager">
- <authentication-provider user-service-ref="myUserDetailsService">
- <password-encoder ref="myPasswordEncode">
- <salt-source user-property="salt"/>
- </password-encoder>
- </authentication-provider>
- </authentication-manager>
- <beans:bean id="myPasswordEncode" class="pw.bany.security.MyPasswordEncode">
- <beans:constructor-arg name="encode" value="md5"></beans:constructor-arg>
- </beans:bean>
如果我们要自己控制密码权限的验证,可以在配置中使用<password-encoder ref="myPasswordEncode">来指定自己的密码验证类,该类继承自MessageDigestPasswordEncoder。需要我们复写了public boolean isPasswordValid(String savePass, String submitPass, Object salt)方法,如果返回true,表示验证通过。上面代码还为MyPasswordEncode传入encode属性,来设置MyPasswordEncode中encode(本文下面的代码没有用到)。这样在isPasswordValid就可以用到需要加密的算法。isPasswordValid中savePass为数据库中加密保存的密码,submitPass为用户登录时提交的明文密码。
- @Override
- // 如果返回true,则验证通过。
- public boolean isPasswordValid(String savePass, String submitPass,
- Object salt) {
- return savePass.equalsIgnoreCase(Util.MD5WithSalt(submitPass,
- salt.toString()));
- }
Util.MD5WithSalt(submitPass,salt.toString()),是我们的加密方法,此处没贴出源码,网上很多。这里的salt需要特别注意一下,怎么才能把数据库中的salt传过来的问题。
上面配置中使用了<salt-source user-property="salt"/>来指定salt,但是系统是怎么知道在数据库中的salt字段呢?其实这里实际上是指定了org.springframework.security.core.userdetails.User中的一个属性,但是这个类中并没有这个属性,此时,需要我们重写这个类,为该类加入salt属性。
- package pw.bany.security;
-
- import java.util.Collection;
- import org.springframework.security.core.GrantedAuthority;
- import org.springframework.security.core.userdetails.User;
-
- public class SaltedUser extends User {
-
- private String salt;
-
- public SaltedUser(String username, String password, boolean enabled,
- boolean accountNonExpired, boolean credentialsNonExpired,
- boolean accountNonLocked,
- Collection<? extends GrantedAuthority> authorities, String salt) {
- super(username, password, enabled, accountNonExpired,
- credentialsNonExpired, accountNonLocked, authorities);
- this.salt = salt;
- }
-
- public String getSalt() {
- return salt;
- }
-
- public void setSalt(String salt) {
- this.salt = salt;
- }
-
- }
完成这里之后,还是不够的,因为重载的类只是有了这个属性,但是还是不知道如何从数据库中获取。要做到这个其实很简单,我们只需要修改myUserDetailsService中loadUserByUsername的返回值:
- @Override
- public UserDetails loadUserByUsername(String username)
- throws UsernameNotFoundException {
- Collection<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();
- User user = null;
- try {
- user = userDao.getUserByName(username);
- if (user == null)
- throw new UsernameNotFoundException("用户" + username + "不存在!");
- List<String> rolenames = userDao.loadRolesByUserName(username);
- System.err.println("用户拥有角色有:");
- for (String rolename : rolenames) {
- SimpleGrantedAuthority authority = new SimpleGrantedAuthority(
- rolename);
- auths.add(authority);
- System.err.println(rolenames);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- System.err.println(auths.size());
- boolean isEnabled = true;
- boolean accountNonExpired = true;
- boolean credentialsNonExpired = true;
- boolean accountNonLocked = true;
-
- if (!user.getStatus().equalsIgnoreCase("enabled")) {
- isEnabled = false;
- }
-
- return new SaltedUser(user.getUsername(), user.getPassword(),
- isEnabled, accountNonExpired, credentialsNonExpired,
- accountNonLocked, auths, user.getSalt());
- }
如上面红色代码部分,一看便知。