一般来说,我们的用户信息都是存放在数据库中的,本章节就基于数据库来完成认证与授权。
数据库设计
这里需要三张表:user(用户信息表)、role(角色表)、user_role(用户与角色关系表)。一般来说,角色与权限相关,所以用户具有什么样的角色,就拥有什么样的权限。
create table `user` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(50) NOT NULL,
`enabled` varchar(50) DEFAULT NULL,
`locked` varchar(50) DEFAULt NULL,
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
create table `role` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
create table `user_role` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`uid` int NOT NULL,
`rid` int NOT NULL,
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Maven依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<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>2.1.3</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
application.yml配置文件
spring:
datasource:
url: jdbc:mysql://localhost:3306/world?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&failOverReadOnly=false&serverTimezone=UTC
type: com.alibaba.druid.pool.DruidDataSource
username: root
password: root
UserDetailsService的实现
UserDetailsService
是由Spring Security提供给我们的接口,如下所示。
public interface UserDetailsService {
UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}
我们可以自定义实现。
@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) {
return user;
}
// 根据用户id查找所具有的角色
List<Role> roles = userMapper.getUserRoleByUid(user.getId());
user.setRoles(roles);
return user;
}
}
Mapper类
@Mapper
public interface UserMapper {
@Select("select * from user where username=#{username}")
User loadUserByUsername(String username);
@Select("SELECT * FROM role r INNER JOIN user_role ur ON r.id = ur.rid WHERE uid=#{id}")
List<Role> getUserRoleByUid(Integer id);
}
实体类
Spring Security的用户都是用 UserDetails
类代表。我们需要实现 UserDetails
接口。
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 true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
// getter or setter 省略
}
WebSecurityConfigurerAdapter配置
@Configuration
public class UserWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
// 密码编码器,这里是明文,不对密码进行加密
@Bean
public PasswordEncoder passwordEncoder() {
return new PasswordEncoder() {
@Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return charSequence.toString().equals(s);
}
};
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasAnyRole("ADMIN")
.anyRequest().authenticated();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);
}
}
备注
本系列都是学习《深入浅出Spring Security》的笔记