(原创)Spring security用户验证机制浅谈.

1.  首先CustomUserDetailsService需要实现UserDetailsService(org.springframework.security.core.userdetails.UserDetailsService)接口, 实现获取用户Detail信息的回调函数. 必须要实现的方法是loadUserByUsername

注意: 这里的user类必须继承userDetail, 并且必须继承

  private  String password;

  private  String username;

  private  Set<GrantedAuthority> authorities;

  private  boolean accountNonExpired;

  private  boolean accountNonLocked;

private  boolean credentialsNonExpired;

这五个属性

hashCode, equals这两个方法;

构造方法中必须给上述的5个属性赋值, CustomUserDetailsService调用构造方法, 生成一个user对象;

如果user不存在, 这里可以直接抛出UsernameNotFoundException异常, 具体流程自己试验下, 前台SPRING_SECURITY_LAST_EXCEPTION显示的错误是:”坏的凭证

 

2.  loadUserByUsername方法返回后会跳到DaoAuthenticationProvider(org.springframework.security.authentication.dao.DaoAuthenticationProvider)类中retrieveUser方法中

3.  retrieveUser方法返回后会跳到

AbstractUserDetailsAuthenticationProvider(org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider) authenticate方法中,这个方法会先到缓存中查找user:

String username =(authentication.getPrincipal() == null) ? "NONE_PROVIDED" : authentication.getName();

boolean cacheWasUsed = true;

UserDetails user = this.userCache.getUserFromCache(username);

 如果没有的话会从上一步DaoAuthenticationProviderloadUserByUsername方法把user查出来。这里会抛UsernameNotFoundException这个异常, 应该是用户不存在这个错误, Bad credentials.

4. authenticate方法里面

preAuthenticationChecks.check(user);这里进行基本有效性验证(是否有效, 是否被锁, 是否过期); 代码如下:

if (!user.isAccountNonLocked()) {

                throw new LockedException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.locked",

                        "User account is locked"), user);

            }

 

            if (!user.isEnabled()) {

                throw new DisabledException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.disabled",

                        "User is disabled"), user);

            }

 

            if (!user.isAccountNonExpired()) {

                throw new AccountExpiredException(messages.getMessage("AbstractUserDetailsAuthenticationProvider.expired",

                        "User account has expired"), user);

            }

 

 

5.  authenticate方法里面

additionalAuthenticationChecks(user,(UsernamePasswordAuthenticationToken) authentication);这里进行密码验证.

additionalAuthenticationChecks调用的是DaoAuthenticationProvider(org.springframework.security.authentication.dao.DaoAuthenticationProvider)中的additionalAuthenticationChecks的方法; 应该是继承的关系;
具体比较的方法写在 Md4PasswordEncoder(
org.springframework.security.authentication.encoding.Md5PasswordEncoder)类中的

 public boolean isPasswordValid(String encPass, String rawPass, Object salt) 方法中; 可是debug中中不到
Md5PasswordEncoder实现的isPasswordValid方法; 这很蹊跷...不过根据配置文件中; 加密方式应该是md5;
<!-- 用户的密码加密或解密 -->
    <bean id="passwordEncoder"
        class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" />

<!-- 注意能够为authentication-manager 设置alias别名  -->
    <authentication-manager alias="authenticationManager">
        <authentication-provider user-service-ref="userDetailsManager">
            <password-encoder ref="passwordEncoder">
                <salt-source user-property="username" />
            </password-encoder>
        </authentication-provider>
    </authentication-manager>
所以应该
Md5PasswordEncoder也有实现isPasswordValid(String encPass, String rawPass, Object salt) 这个方法;

至于前台password怎么传到这里; spring security拦截了j_spring_security_check请求; 并把j_password赋给了
DaoAuthenticationProvider(org.springframework.security.authentication.dao.DaoAuthenticationProvider)中passwordEncoder属性; 这个还没验证过;

/** auth 张振斌, time: 2012-12-3**/  QQ:739934487

猜你喜欢

转载自blog.csdn.net/d7011800/article/details/8692667