SpringBoot安全管理 ——模块2:Spring Security 基于数据库的认证

Spring Security 基于数据库的认证

上一篇所介绍的认证数据都是直接定义在内存中,而在真实项目中,用户的信息肯定都是存放在数据库中,因此如何从数据库中获取数据进行认证,本篇将介绍如何基于数据库做认证

1.设计数据库
首先需要设计一个数据库,里面有三张表,分别是用户表,角色表,用户角色关联表
user 表字段如下:
在这里插入图片描述
role 表字段如下:
在这里插入图片描述
user_role 表字段如下:
在这里插入图片描述
2.创建项目
首先在pom.xml文件中添加如下依赖:

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

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

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.0</version>
        </dependency>

3.配置数据库,在application.properties中配置数据库的基本信息:

spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql:///security

4.创建实体类
这里分别创建角色类和用户表对应的实体类,如下所示:

public class Role implements Serializable {
    private Integer id;
    private String name;
    private String nameZh;
 	//省略 getter/setter  
}


//user表所引用的包
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class User implements UserDetails {
    private Integer id;
    private String username;
    private String password;
    private Boolean enabled;
    private Boolean locked;
    private List<Role> roles;
    
    @Override //获取当前对象所具有的角色信息
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<SimpleGrantedAuthority> authorities = new ArrayList<>();
        for (Role role : roles) {
            authorities.add(new SimpleGrantedAuthority(role.getName()));
        }
        return authorities;
    }
    @Override //获取当前用户对象的密码
    public String getPassword() {
        return password;
    }

    @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;
    }
    //省略 getter/setter  
}

代码解释:用户实体类需要实现 UserDetails 接口,并实现该接口中的7个方法,如表所示:

方法名 解释
getAuthorities() 获取当前对象所具有的角色信息
getPassword() 获取当前用户对象的密码
getUsername() 获取当前对象的用户名
isAccountNonExpired() 当前账户是否未过期
isAccountNonLocked() 当前账户是否未锁定
isCredentialsNonExpired() 当前账户密码是否未过期
isEnabled() 当前账户是否可用

5.创建UserService,代码如下:

import com.example.demo.dao.UserMapper;
import com.example.demo.entity.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class UserService implements UserDetailsService {

    @Resource
    UserMapper userMapper;

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

代码解释:定义 UserService 实现 UserDetailsService 接口,并实现此接口的loadUserByUsername 方法,此方法参数就是用户登陆时输入的用户名,通过用户名去数据库查找用户,此方法将在用户登录时自动调用
UserMapper 代码如下:

@Mapper
public interface UserMapper {
    User loadUserByUsername(String username);
    List<Role> getUserRolesByUid(Integer id);
}

UserMapper.xml 代码如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.example.demo.dao.UserMapper">
    <select id="loadUserByUsername" resultType="com.example.demo.entity.User">
        select * from user where username = #{username}
    </select>
    <select id="getUserRolesByUid" resultType="com.example.demo.entity.Role">
        select * from role r,user_role ur where r.id=ur.rid and ur.uid = #{id}
    </select>
</mapper>

6.配置 Spring Security,代码如下

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    UserService userService;

    @Bean
    PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService);
    }
     @Override
    protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
                .antMatchers("/admin/**").hasRole("admin")
                .antMatchers("/db/**").hasRole("dba")
                .antMatchers("/user/**").hasRole("user")
                .anyRequest().authenticated()
                .and()
                .formLogin().loginProcessingUrl("/login").permitAll()
                .and()
                .csrf().disable();
	}
}

这里大部分代码同上篇没有多大改变,唯一不同之处就是没有配置用户,而是将刚刚创建好的 UserService 配置到 AuthenticationManagerBuilder 中
配置完后,接下来就可以创建 Controller 进行测试了。

发布了24 篇原创文章 · 获赞 47 · 访问量 4087

猜你喜欢

转载自blog.csdn.net/qq_43647359/article/details/104520699
今日推荐