使用 Spring Boot Security 实现登录验证

243 阅读2分钟

Security的运行流程

1、客户端发送一个登录请求

2、请求通过Security的过滤器链

3、Spring Boot 调用实现 UserDetailsService 接口的类获取后端保存的用户信息

4、将客户端发来的用户信息加密后 与 数据库保存的用户信息对比

5、若成功,则允许登录,然后响应消息经过过滤器链返回给客户端。

UserDetailsService 接口的实现

1、创建一个类,此类 实现 UserDetailsService接口

2、重写 loadUserByUsername 方法

此方法的作用:通过用户名加载用户,这个方法需要返回一个实现UserDetails接口的类,类里封装用户信息。

@Service
public class UserDetailsServiceImpl implements UserDetailsService{
    

    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        /* 
           使用构造器从数据库内查找用户名为username的用户,并构造返回一个 UserDetailsImpl 类
           此类即为实现了UserDetails接口的类
        */
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("username", username);
        User user = userMapper.selectOne(queryWrapper);
        if(user == null) throw new RuntimeException("user is not exist!");
        return new UserDetailsImpl(user);
    }
    
    
}

UserDetails 接口类: 用于封装用户信息,包括用户名、密码、权限等。

// lombok 依赖,帮助写一些很无聊的方法
@Data
@AllArgsConstructor
@NoArgsConstructor

// 这个接口允许你自定义用户信息的存储和检索方式
public class UserDetailsImpl implements UserDetails {
    // 封装的用户信息
    User user;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return Collections.emptyList();
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }
    //判断账户信息是否有效
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    // 判断账户是否被锁定
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }
    // 判断身份信息是否有效
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    // 判断此用户是否启用 
    @Override
    public boolean isEnabled() {
        return true;
    }
}

加密工具类

此加密工具被Security用来对用户密码进行加密,数据库内存储的用户密码是被这个加密工具类加密后的密码。 等客户端发来登录请求后,Security会用此加密工具对用户的登录密码加密,然后和数据库内的密码对比。

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public PasswordEncoder passwordEncoder() {
        // 数据库里面的密码也使用此类进行密码加密
        return new BCryptPasswordEncoder();
    }
}