SpringSecurity用户认证设置用户名和密码的三种方式

文章目录

  • SpringSecurity用户认证设置用户名和密码的三种方式
    • 首先明白几个单词的意思:
    • SpringSecurity默认的用户认证
    • 1.通过配置文件进行用户认证
    • 2.通过配置类进行用户认证
      • There is no PasswordEcoder mapped for the id "null"异常
        • 异常出现原因
        • 解决办法
          • 在内存中存取密码方式
      • PasswordEncoder接口
    • 3.通过自定义编写用户细节实现类(需要查询数据库)进行用户认证
      • 数据库中的表
      • 数据库中的表对应的java bean实体类
      • 基于数据库自定义的用户细节实现类
      • UserDetailsService接口
      • SpringSecurity配置类

SpringSecurity用户认证设置用户名和密码的三种方式

首先明白几个单词的意思:

Authentication:认证

AuthenticationManagerBuilder:身份验证管理器生成器

encoder:编译器

PasswordEncoder:密码编译器

SpringSecurity默认的用户认证

先来看一下假如用SpringSecurity默认的用户认证,用户名和密码是什么?

SpringSecurity用户认证设置用户名和密码的三种方式_第1张图片

SpringSecurity用户认证设置用户名和密码的三种方式_第2张图片

1.通过配置文件进行用户认证

SpringSecurity用户认证设置用户名和密码的三种方式_第3张图片

下面来看一下SecurityAutoConfiguration.class自动配置类,如下图

SpringSecurity用户认证设置用户名和密码的三种方式_第4张图片

下面再来看一下SecurityProperties.class类,如下图:

SpringSecurity用户认证设置用户名和密码的三种方式_第5张图片

SpringSecurity用户认证设置用户名和密码的三种方式_第6张图片

2.通过配置类进行用户认证

首先配置类需要继承WebSecurityConfigurerAdapter适配器类,WebSecurityConfigurerAdapter 类是个适配器, 在配置的时候,需要我们自己写个配置类去继承他,然后编写自己所特殊需要的配置。

SpringSecurity用户认证设置用户名和密码的三种方式_第7张图片

也可以同时把多个用户信息以及它们的权限存到内存中,只需要在多个用户信息之间用and()方法连接就行了

 // 自定义配置认证规则
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
     
        auth.inMemoryAuthentication()
                .withUser("zhangsan").password("12345").roles("SuperAdmin")
                .and()
                .withUser("lisi").password("12345").roles("Admin")
                .and()
                .withUser("wangwu").password("12345").roles("Employee");

    }

There is no PasswordEcoder mapped for the id "null"异常

异常出现原因

下面重点描述一下上图中所说的There is no PasswordEcoder mapped for the id "null"异常,以及谈谈它的解决办法:

Spring security 5.0中新增了多种加密方式,也改变了默认的密码格式.

我们来看一下官方文档:

The general format for a password is:
{id}encodedPassword

Such that id is an identifier used to look up which PasswordEncoder should be used and encodedPassword is the original encoded password for the selected PasswordEncoder. The id must be at the beginning of the password, start with { and end with }. If the id cannot be found, the id will be null. For example, the following might be a list of passwords encoded using different id. All of the original passwords are "password".

{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG 

{noop}password 

{pbkdf2}5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc 

{scrypt}$e0801$8bWJaSu2IKSn9Z9kM+TPXfOc/9bdYSrN1oD9qfVThWEwdRTnO7re7Ei+fUZRJ68k9lTyuTeUp4of4g24hHnazw==$OAOec05+bXxvuu/1qZ6NUR+xQYvYv7BeL1QxwRpY5Pc=  

{sha256}97cde38028ad898ebc02e690819fa220e88c62e0699403e94fff291cfffaf8410849f27605abcbc0

**这段话的意思是说,现如今Spring Security中密码的存储格式是“{id}…………”.前面的id是加密方式,id可以是bcrypt、sha256等,后面跟着的是加密后的密码.也就是说,程序拿到传过来的密码的时候,会首先查找被“{”和“}”包括起来的id,来确定后面的密码是被怎么样加密的,如果找不到就认为id是null.**这也就是为什么我们的程序会报错:There is no PasswordEncoder mapped for the id “null”.官方文档举的例子中是各种加密方式针对同一密码加密后的存储形式,原始密码都是“password”.

解决办法

需要修改一下configure中的代码,我们要将前端传过来的密码进行某种方式加密,Spring Security 官方推荐的是使用bcrypt加密方式.

在内存中存取密码方式

是这样的:

protected void configure(AuthenticationManagerBuilder auth) throws Exception {
     

  //inMemoryAuthentication 从内存中获取

  auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()).withUser("user1").password(new BCryptPasswordEncoder().encode("123")).roles("USER");

}

inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())",这相当于登陆时用BCrypt加密方式对用户密码进行处理.以前的".password(“123”)" 变成了 “.password(new BCryptPasswordEncoder().encode(“123”))”,这相当于对内存中的密码进行Bcrypt编码加密.如果比对时一致,说明密码正确,才允许登陆.

总结:在用户进行用户认证登录的时候,前端传来的密码会用BCrpt加密方式进行加密,加密后的密码格式是{id}password,然后程序员会先获取到加密方式也即是{id},假设没有写passwordEncoder(new BCryptPasswordEncoder())那么前端传来的值就不会用BCrpt加密方式进行加密,所以程序员获取前端传来的值时是寻找不到密码中的{id}也即是加密方式的,因此就会报There is no PasswordEcoder mapped for the id "null"异常。passwordEncoder(new BCryptPasswordEncoder())可以理解成是告诉系统到底用什么样的加密方式对前端传来的数据进行加密。假设程序中用了passwordEncoder(new BCryptPasswordEncoder())那么获取到用bcrypt加密方式的密码后会和内存中存储的用bcrypt方式进行加密的密码进行比较,如果相同那么说明用户输入的密码和内存中的密码一致,则允许登录。

PasswordEncoder接口

SpringSecurity用户认证设置用户名和密码的三种方式_第8张图片

BCryptPasswordEncoder是PasswordEncoder接口的实现类
SpringSecurity用户认证设置用户名和密码的三种方式_第9张图片

在对密码加密的时候需要调用相关的实现类如BCryptPasswordEncoder的encode方法,当用户在登录时,就会自动调用 matches 方法进行密码比对。

3.通过自定义编写用户细节实现类(需要查询数据库)进行用户认证

数据库中的表

首先先来看一下数据库中的users表,如下图:

SpringSecurity用户认证设置用户名和密码的三种方式_第10张图片

数据库中的表对应的java bean实体类

SpringSecurity用户认证设置用户名和密码的三种方式_第11张图片

基于数据库自定义的用户细节实现类

自定义的用户细节实现类如下图:

SpringSecurity用户认证设置用户名和密码的三种方式_第12张图片

UserDetailsService接口

SpringSecurity用户认证设置用户名和密码的三种方式_第13张图片

SpringSecurity配置类

SpringSecurity用户认证设置用户名和密码的三种方式_第14张图片

你可能感兴趣的:(SpringSecurity)