爆破专栏丨Spring Security系列教之基于自定义数据库模型实现授权_

文章介绍了如何使用UserDetails类和自定义数据库模型实现SpringSecurity的认证和授权功能,包括创建User实体类、UserMapper接口、UserDetailsService接口的实现以及SecurityConfig的配置。
摘要由CSDN通过智能技术生成

从UserDetails的源码中我们了解到,UserDetails其实就是一个包含了User信息的类,其中包含了用户名、密码、角色及账号状态等信息。


**利用以上的两个核心API,我们就可以进行基于自定义数据库模型的认证授权工作了,**因为不管我们项目中关于认证、授权的数据库结构如何变化,只要我们构造出一个UserDetails类,然后利用UserDetailsService进行用户信息的加载就可以了。


**二. 基于自定义数据库模型实现授权**


**1. 创建数据库**


在开始今天的代码之前,请先跟着壹哥来创建一个数据库,并在该库里创建用户角色表,建表脚本如下:



CREATE TABLE users (id bigint(20) NOT NULL AUTO_INCREMENT,
        username varchar(50) NOT NULL,
        password varchar(60) NOT NULL,
        enable tinyint(4) NOT NULL DEFAULT 1,
        roles text character set utf8,
        PRIMARY KEY (id),
        KEY username (username)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;


该表中包含了用户名、密码、角色、可用状态等信息,然后我们在该表中添加一些测试数据,如下图所示:


![图片](https://img-blog.csdnimg.cn/img_convert/804e7c4ca58b2deddf0dfdd505ac0c98.png)


**2. 创建项目**


准备好了数据库之后,**我们就继续在之前项目的基础之上,创建一个新的model模块,**其基本配置信息和之前一样,具体创建过程略,请参考之前的章节进行项目创建!


**3. 创建User实体类**



/**
 * 用户操作实体类
 */
public class User implements UserDetails {

private Long id;

private String username;

private String password;

private String roles;

private boolean enable;

private List authorities;

public String getRoles() {
        return roles;
    }

public void setRoles(String roles) {
        this.roles = roles;
    }

public Long getId() {
        return id;
    }

public void setId(Long id) {
        this.id = id;
    }

public boolean isEnable() {
        return enable;
    }

public void setEnable(boolean enable) {
        this.enable = enable;
    }

@Override
    public String getUsername() {
        return username;
    }

public void setUsername(String username) {
        this.username = username;
    }

@Override
    public boolean isAccountNonExpired() {
        return true;
    }

@Override
    public boolean isAccountNonLocked() {
        return true;
    }

@Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

@Override
    public boolean isEnabled() {
        return this.enable;
    }

public void setAuthorities(List authorities) {
        this.authorities = authorities;
    }

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

@Override
    public String getPassword() {
        return password;
    }

public void setPassword(String password) {
        this.password = password;
    }

@Override
    public boolean equals(Object obj) {

return obj instanceof User?this.username.equals(((User)obj).username):false;
    }

@Override
    public int hashCode() {
        return this.username.hashCode();
    }

}


在刚才的模块里,我们先创建一个User实体类,这个用户实体类需要实现 **UserDetails** 接口,并实现接口中的方法。


**核心方法介绍:**


* accountNonExpired、accountNonLocked、credentialsNonExpired、enabled 这四个属性分别用来描述用户的状态,表示账户是否没有过期、账户是否没有被锁定、密码是否没有过期、以及账户是否可用;
* roles 属性表示用户的角色;
* getAuthorities 方法返回用户的角色信息,一个用户可能会有多个角色,所以这里返回值是一个集合类型,我们在这个方法中把自己的 Role 角色稍微转化一下即可。


**4. 定义Mapper接口**


数据模型准备好之后,我们再来定义一个 UserMapper接口,这里我们利用Mybatis进行具体的数据库查询,直接利用注解的方式实现即可。



/**
 * @Mapper注解,可带可不带,因为有MapperScan扫描.
 */
@Mapper
public interface UserMapper {

@Select(“SELECT * FROM users WHERE username=#{username}”)
    User findByUserName(@Param(“username”) String username);

}


**5. 实现UserDetailsService接口**


接在在service层,定义一个UserDetailsService子类,**实现UserDetailsService接口**,然后实现该接口中的loadUserByUsername()方法。这个方法的参数是用户在登录的时候传入的用户名,然后根据用户名去查询用户信息(查出来之后,系统会自动进行密码比对)。



@Service
public class MyUserDetailsService implements UserDetailsService {

@Autowired
    private UserMapper userMapper;

@Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 从数据库尝试读取该用户
        User user = userMapper.findByUserName(username);
        
        // 用户不存在,抛出异常
        if (user == null) {
            throw new UsernameNotFoundException(“用户不存在”);
        }
        
        // 将数据库形式的roles解析为UserDetails的权限集
        // AuthorityUtils.commaSeparatedStringToAuthorityList是Spring Security
        //提供的用于将逗号隔开的权限集字符串切割成可用权限对象列表的方法
        // 当然也可以自己实现,如用分号来隔开等,参考generateAuthorities
        user.setAuthorities(AuthorityUtils.commaSeparatedStringToAuthorityList(user.getRoles()));
        return user;
    }

}


主要要在实现方法中,利用user对象的setAuthorities()方法关联用户的所有角色信息,否则用户登录认证时就没有角色,认证也会失败。


**6. 配置SecurityConfig类**


编写完上面的UserDetailsService接口后,接下来我们创建SecurityConfig配置类,我们在configure方法中,关联配置自定义的UserService对象。



@EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers(“/admin/“)
                .hasRole(“ADMIN”)
                .antMatchers(”/user/
”)
                .hasRole(“USER”)
                .antMatchers(“/visitor/**”)
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()
                .permitAll();
    }

/在数据库中创建用户和角色*************/

@Autowired
    private MyUserDetailsService userDetailsService;

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //关联UserDetailsService对象

最后总结我的面试经验

2021年的金三银四一眨眼就到了,对于很多人来说是跳槽的好机会,大厂面试远没有我们想的那么困难,摆好心态,做好准备,你也可以的。

另外,面试中遇到不会的问题不妨尝试讲讲自己的思路,因为有些问题不是考察我们的编程能力,而是逻辑思维表达能力;最后平时要进行自我分析与评价,做好职业规划,不断摸索,提高自己的编程能力和抽象思维能力。

BAT面试经验

实战系列:Spring全家桶+Redis等

其他相关的电子书:源码+调优

面试真题:

g-rZJ86Rld-1714755350971)]

BAT面试经验

实战系列:Spring全家桶+Redis等

[外链图片转存中…(img-96iXb0vV-1714755350971)]

其他相关的电子书:源码+调优

[外链图片转存中…(img-MmeMKTgo-1714755350972)]

面试真题:

[外链图片转存中…(img-KYoKvpbp-1714755350972)]

[外链图片转存中…(img-DfIMBJrH-1714755350973)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 16
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值