Bootstrap

学习SpringSecurity的日常生活(四)—— 自定义数据源


前言

上一次我们实现了SpringSecurity的前后端分离,这次我们把里面的内存数据源改成数据库。

一、整合mybatis

1、pom.xml里面引入jar包

<!-- mysql驱动 -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.38</version>
</dependency>

<dependency>
    <groupId>org.mybatis.spring.boot.</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>

2、application配置文件

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name: com.mysql.jdbc.Driver
spring.datasource.url: jdbc:mysql://localhost:3306/security?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
spring.datasource.username: root
spring.datasource.password: yuanyuan

mybatis.mapper-locations= classpath:mapper/*.xml
mybatis.type-aliases-package=com.spring.security/entity

logging.level.com.spring.security=debug

3、业务代码

1、mapper.xml代码如下:

<mapper namespace="com.spring.security2.dao.UserDao">
   <select id="loaduserbyusername" resultType="com.spring.security2.entity.User">
       select id,username,password,enabled,accountNonExpired,accountNonLocked,credentialsNonExpired
       from user where username=#{username}
   </select>

   <select id="getrolebyuserid" resultType="com.spring.security2.entity.Role">
       select a.id,a.name,a.name_zh
       from role a
       left join user_role b on a.id=b.rid
       where b.uid=#{uid}
   </select>
</mapper>

2、dao层代码如下:

@Mapper
public interface UserDao {

    User loaduserbyusername(String name);

    List<Role> getrolebyuserid(int uid);
}

3、service代码如下:

@Service
public class UserServiceImpl implements UserDetailsService {

    @Autowired
    private UserDao userDao;

    @Override
    public UserDetails loadUserByUsername(String name) {
        User user = userDao.loaduserbyusername(name);
        if(ObjectUtils.isEmpty(user)){
            throw new UsernameNotFoundException("用户名不正确");
        }else{
            user.setList(userDao.getrolebyuserid(user.getId()));
        }
        return user;
    }
}

这里UserServiceImpl 要实现UserDetailsService 接口,因为我们要用我们自定义的

UserServiceImpl 代替之前的InMemoryUserDetailsManager,

InMemoryUserDetailsManager也是实现的UserDetailsService 。

4、实体类,代码如下:

public class User implements Serializable,UserDetails {

    private static final long serialVersionUID = 1L;

    private int id;
    private String username;
    private String password;

    private boolean accountNonExpired;
    private boolean accountNonLocked;
    private boolean credentialsNonExpired;
    private boolean enabled;

    private List<Role> list = new ArrayList<>();

    public Collection<GrantedAuthority> getAuthorities() {
        Set authorities = new HashSet();
        list.forEach(role->{
            SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(role.getName());
            authorities.add(simpleGrantedAuthority);
        });
        return authorities;
    }

    public int getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

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

    public String getPassword() {
        return password;
    }

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

    public boolean isAccountNonExpired() {
        return accountNonExpired;
    }

    public void setAccountNonExpired(boolean accountNonExpired) {
        this.accountNonExpired = accountNonExpired;
    }

    public boolean isAccountNonLocked() {
        return accountNonLocked;
    }

    public void setAccountNonLocked(boolean accountNonLocked) {
        this.accountNonLocked = accountNonLocked;
    }

    public boolean isCredentialsNonExpired() {
        return credentialsNonExpired;
    }

    public void setCredentialsNonExpired(boolean credentialsNonExpired) {
        this.credentialsNonExpired = credentialsNonExpired;
    }

    public boolean isEnabled() {
        return enabled;
    }

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

    public List<Role> getList() {
        return list;
    }

    public void setList(List<Role> list) {
        this.list = list;
    }
}

实体类继承UserDetails

public class Role implements Serializable {
    private static final long serialVersionUID = 1L;
    private int id;
    private String name;
    private String nameZh;

    public int getId() {
        return id;
    }

    public void setId(int 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;
    }
}
public class UserRole implements Serializable {
    private static final long serialVersionUID = 1L;
    private int id;
    private int uid;
    private int rid;

    public int getId() {
        return id;
    }

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

    public int getUid() {
        return uid;
    }

    public void setUid(int uid) {
        this.uid = uid;
    }

    public int getRid() {
        return rid;
    }

    public void setRid(int rid) {
        this.rid = rid;
    }
}

5、数据库
在这里插入图片描述

4、Security配置

引入我们自定义的UserServiceImpl ,并把auth.userDetailsService(userDetailService())替换成auth.userDetailsService(userServiceImpl)
代码如下:

@Autowired
private UserServiceImpl userServiceImpl;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userServiceImpl);
}

二、测试

在这里插入图片描述
可以看到把数据源改成数据库成功了


总结

改完了数据库,下次就该到验证码了,毕竟我们登录都是有验证码的。

完整代码地址:https://pan.baidu.com/s/1EPlg81uW0hbCQBGRkrjJow
提取码:xxgz

我的个人博客地址http://www.dbhx.vip

;