Spring Security(三):用户自定义认证逻辑

上一篇进行了最简单的Spring Security的初始搭建,像用户名和密码都是固定的,这篇就来讲讲自定义用户认证逻辑的实现,包括用户信息的获取,用户密码的校验以及用户密码的加密校验。

处理用户信息获取逻辑

源码

  • 用户信息的获取逻辑被封装在UserDetailsService接口中,接口源码:
public interface UserDetailsService {
    UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}
  • 作用:根据用户前端输入的用户名,会到存储去读取用户信息封装到返回值UserDetails中,如果通过输入的用户名没法找到数据库中数据,则会抛出一个UsernameNotFoundException异常。

实操

  • 我们可以创建自己的一个MyUserDetailsService,实现上面的接口,在loadUserByUsername方法中进行一个数据库用户信息的查询返回。
@Component
public class MyUserDetailsService implements UserDetailsService {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyUserDetailsService.class);

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        LOGGER.info("登录名:" + username);
        // balabala,根据用户名查找用户密码等信息返回(记得实际开发中是查库得到的),第三个参数是用户授权,后面再来详细讲
        return new User(username, "123456", AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}
  • 效果:任意用户名,密码是123456才能进行登录(假装上面的密码是数据库中查到的!)
    用户登录

处理用户校验逻辑

源码

  • UserDetails接口解析,该接口用于返回用户信息。
public interface UserDetails extends Serializable {
    /**
     * 用户授权
     */
    Collection<? extends GrantedAuthority> getAuthorities();
    /**
     * 用户密码
     */
    String getPassword();
    /**
     * 用户名
     */
    String getUsername();
    /**
     * 以下四个方法可以自定义校验逻辑,返回账户是否过期,true表示没有过期
     */
    boolean isAccountNonExpired();
    /**
     * 账户是否被锁定或者冻结(一般可恢复),true表示没被冻结
     */
    boolean isAccountNonLocked();
    /**
     * 密码是否过期,true表示没有过期,可能有的网站需求密码需要30天更换等
     */
    boolean isCredentialsNonExpired();
    /**
     * 账户是否可用或者是否被删(一般不可恢复),true表示可用
     */
    boolean isEnabled();
}

实操

  • 演示:以上四个boolean类型的方法只要有一个不为true都不能够通过登录校验
@Component
public class MyUserDetailsService implements UserDetailsService {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyUserDetailsService.class);

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        LOGGER.info("登录名:" + username);
        // balabala,根据用户名查找用户密码等信息返回,第三个参数是用户授权,后面再来详细讲
        return new User(username, "123456",
                true, true, true, false,
                AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}

演示

处理密码加密解码

源码

  • PasswordEncoder接口解析,该接口用于密码的加密解密
public interface PasswordEncoder {
    /**
     * 密码加密,在注册的时候,密码插入数据库之前需要你手动调用进行一个加密操作
     */
    String encode(CharSequence var1);
    /**
     * 判断加密的密码和用户传过来的密码是否匹配,该方法由security调用,匹配上了返回true,否则返回false
     */
    boolean matches(CharSequence var1, String var2);
}

实操

  1. 配置上面接口的一个实例Bean。
	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}
  1. 记得我们的密码是被加密的,所以数据库中的密码应该是被加密过的。
public class MyUserDetailsService implements UserDetailsService {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyUserDetailsService.class);
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        LOGGER.info("登录名:" + username);
        // balabala,根据用户名查找用户密码等信息返回,第三个参数是用户授权,后面再来详细讲
        String password = passwordEncoder.encode("123456");
        return new User(username, password,
                true, true, true, false,
                AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }
}
  1. 演示,结果就是输入正确密码才能登陆,这里我们发现对同一个密码加密后的密文是不一样的,这是BCryptPasswordEncoder提供的加密方式,当然你可以自己实现加密,比如MD5加密方式等。
    演示

发布了117 篇原创文章 · 获赞 309 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_36221788/article/details/105463055