案例代码在:https://github.com/stuchangan/springboot-study/tree/master/security-db
运行案例前请运行文件里的sql文件。
1、创建项目导入依赖
获取数据库中的信息 就需要添加数据库依赖、连接池以及mybatis。其他数据库也可以
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<!--连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.14</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
<version>5.1.44</version>
</dependency>
2、修改pom文件
使用mybatis时需要用到mapper.xml文件在springboot中静态文件需要放在resources文件夹下
一般编码习惯将mapper接口文件以及xml文件放在一起(java文件夹下),这时就需要在pom文件中添加下面配置,将下面配置写在<build><build/>里面 这样springboot就会去扫描java文件夹下的静态文件
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
3、创建实体类
创建user实体类和role实体类,其中user实体类要实现UserDetails接口
user类:
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
public Collection<? extends GrantedAuthority> getAuthorities() {
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
for (Role role : roles) {
//在springsecurity中角色是以 ROLE_ 开头的
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;
}
}
4、security配置
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserService userService;
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
//springSecurity中的角色传递
@Bean
RoleHierarchy roleHierarchy(){
RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
//表示ROLE_dba的权限大于ROLE_admin,ROLE_admin的权限大于ROLE_user
String hierarchy = "ROLE_dba > ROLE_admin \n ROLE_admin > ROLE_user";
roleHierarchy.setHierarchy(hierarchy);
return roleHierarchy;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);
}
@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();
}
}
5、mapper层编写
UserMapper.java:
@Mapper
public interface UserMapper {
//根据用户名查询user对象
User loadUserByUsername(String username);
//根据用户id查询用户具有的角色
List<Role> getUserRolesById(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.javaboy.securitydb.mapper.UserMapper">
<select id="loadUserByUsername" resultType="com.javaboy.securitydb.entity.User">
select * from user where username=#{username}
</select>
<select id="getUserRolesById" resultType="com.javaboy.securitydb.entity.Role">
select * from role where id in (select rid from user_role where uid=#{id})
</select>
</mapper>
6、service编写
UserService要实现UserDetailsService接口
@Service
public class UserService 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;
}
}
7、controller层
三个接口分别表示不同的角色可以访问的不同接口
@RestController
public class UserController {
@GetMapping("/dba/hello")
public String dba(){
return "hello dba";
}
@GetMapping("/admin/hello")
public String admin(){
return "hello admin";
}
@GetMapping("/user/hello")
public String user(){
return "hello user";
}
}