学习笔记——在Springboot中使用spring security(三):基于数据库的认证

一、前言

前几篇博客在内存配置的基础上简单了解了一下spring security中的一些配置。但是用户不可能是在内存中写死的,这篇博客就配合mybatis学习一下基于数据库的认证如何配置。

二、开整

2.1、准备数据库

首先准备一下数据库
这篇主要用到这几个表
用户表
在这里插入图片描述
角色表
在这里插入图片描述
用户角色关联表
在这里插入图片描述

2.2、准备实体类

User类
在spring security中需要准备一个UserDetails的实现类用来存储用户的基本信息,这些信息会被封装在Authentication对象中。随后会多次使用到Authentication这个类。

(只是这里是做一个简单的例子,所以部分属性没有配置。)

public class User implements UserDetails {
    private Integer id;
    private String username;
    private String password;
    private Boolean enabled;
    private Boolean locked;
    private List<Role> roles;

    public List<Role> getRoles() {
        return roles;
    }

    public void setRoles(List<Role> roles) {
        this.roles = roles;
    }

    public Integer getId() {
        return id;
    }

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

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

    @Override
    // 账户未过期
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    // 账户未锁定
    public boolean isAccountNonLocked() {
        return !locked;
    }

    @Override
    // 凭证(密码)未过期过期
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    // 用户是否可用
    public boolean isEnabled() {
        return enabled;
    }

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

    @Override
    // 用户的角色列表,需要将角色名称封装进SimpleGrantedAuthority对象中
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for (Role role : roles) {
            authorities.add(new SimpleGrantedAuthority("ROLE_"+role.getName()));
        }
        return authorities;
    }

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

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

    public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
    }

    public void setLocked(Boolean locked) {
        this.locked = locked;
    }
}

Role类

public class Role {
    private Integer id;
    private String name;
    private String nameZh;

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getNameZh() {
        return nameZh;
    }

    public void setNameZh(String nameZh) {
        this.nameZh = nameZh;
    }
}
2.3、准备UserDetailsService的实现类

前面我们的User类实现了UserDetails接口。在这里我们还要实现一个UserDetailsService接口,这个接口中只定义了一个方法loadUserByUsername。这个方法主要是验证用户是否存在,允许抛出UsernameNotFoundException异常。

@Service("userServiceImpl")
public class UserServiceImpl implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userMapper.loadUserByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在!");
        }
        user.setRoles(userMapper.getUserRolesById(user.getId()));
        return user;
    }
}

2.4、准备配置类
@Configuration
public class SecurityDbConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userServiceImpl;

    @Bean
    // 密码加密方式
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    @Override
    // 配置身份验证
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userServiceImpl);
    }

    @Override
    // 在内存中配置路径资源权限
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
                .antMatchers("/dba/**").hasRole("dba")
                .antMatchers("/admin/**").hasRole("admin")
                .antMatchers("/user/**").hasRole("user")
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .permitAll()
                .and()
                .csrf().disable();
    }
}
2.5、测试

随便准备一个Controller,登录不同的用户访问这些接口,有相应权限的可以正常访问,反之则不能。

@RestController
public class HelloSpringBoot {

    @GetMapping("/SpringBoot")
    public String hello() {
        return "Hello SpringBoot!";
    }

    @GetMapping("/admin/hello")
    public String helloAdmin() {
        return "Hello admin!";
    }
    
    @GetMapping("/user/hello")
    public String helloUser() {
        return "Hello user!";
    }

    @GetMapping("/dba/hello")
    public String helloDba() {
        return "hello dba!";
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值