一、设计数据表二、创建项目三、配置数据库四、创建实体类五、创建UserService六、配置Spring Security七、Controller
一、设计数据表在真实项目中,用户的基本信息以及角色等都存储在数据库中,因此需要从数据库中获取数据进行认证。
首先需要设计一个基本的用户角色表。一共三张表,分别是用户表、角色表以及用户角色关联表。
角色名有一个默认的前缀“ROLE_”。
Mybatis灵活,JPA便利,本案例选择前者,因此创建SpringBootWeb项目添加如下依赖 :
4.0.0 org.springframework.boot spring-boot-starter-parent 2.6.3 com.securityone securityone 1.0-SNAPSHOT src/main/java ** public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public void setUsername(String username) { this.username = username; } public void setPassword(String password) { this.password = password; } public Boolean getEnable() { return enable; } public void setEnable(Boolean enable) { this.enable = enable; } public Boolean getLocked() { return locked; } public void setLocked(Boolean locked) { this.locked = locked; } public List getRoles() { return roles; } public void setRoles(List roles) { this.roles = roles; } }
User表中解释:
| UserDetails接口的7个方法 | |
|---|---|
| 方法名 | 解释 |
| getAuthorities | 获取当前用户对象所具有的角色信息 |
| getPassword | 获取当前用户对象的密码 |
| getUsername | 获取当前用户对象的用户名 |
| isAccountNonExpired | 当前账户是否未过期 |
| isAccountNonLocked | 当前账户是否未锁定 |
| isCredentialsNonExpired | 挡前账户密码是否未过期 |
| isEnabled | 当前账户是否可用 |
用户根据实际情况设置这7个方法的返回值。因为默认情况下不需要开发者自己进行密码角色等信息的比对,开发者只需要提供相关信息即可,例如getPassword()方法返回的密码和用户输入的登录密码不匹配,会自动抛出异常。getAuthorities() 方法用来获取当前用户所具有的角色信息,本案例中,用户所具有的的角色存储在roles属性中,因此该方法直接遍历roles属性,然后构造SimpleGrantedAuthority集合并返回。 五、创建UserService
接下来创建UserService,代码如下:
package com.security1.service;
import com.security1.dao.UserMapper;
import com.security1.vo.Role;
import com.security1.vo.User;
import org.springframework.beans.factory.annotation.Autowired;
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;
import java.util.List;
@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;
}
public List getUserRoleByUid(Integer id) {
return userMapper.getUserRolesByUid(id);
}
}
代码解释:
- 定义UserService实现UserDetailsService接口,并实现该接口中的loadUserByUsername方法,该方法的参数就是用户登录时输入的用户名,通过用户名去数据库中查找用户,如果没有查找到用户,就抛出一个账户不存在的异常,如果查找到了用户,就继续查找该用户所具有的的角色信息,并将获取到的user对象返回,再由系统提供的DaoAuthenticationProvider类去比对密码是否正确。loadUserByUsername方法将在用户登录时自动调用。
UserMapper
@Mapper
public interface UserMapper {
User loadUserByUsername(String username);
List getUserRolesByUid(Integer id);
}
UserMapper.xml
六、配置Spring Securityselect * from user where username = #{username}
接下来对Spring Security进行配置,代码如下:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserService userService;
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(10);
}
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);
}
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin
@Controller
public class UserController {
@Autowired
UserService userService;
//具有admin权限
@GetMapping("/admin/hello")
@ResponseBody
public String admin() {
return "hello admin!";
}
//具有user权限
@GetMapping("/user/hello")
@ResponseBody
public String user() {
return "hello user!";
}
//具有db权限
@GetMapping("/db/hello")
@ResponseBody
public String dba() {
return "hello dba!";
}
}
根据WebSecurityConfig中配置的角色配置,在结合Controller中的三个方法进行测试得出:具有admin角色用户可以访问admin/hello、具有user角色的用户可以访问user/hello、具有dba角色的用户可以访问db/hello。也就是root用户可以访问admin/hello和dba/hello,admin用户可以访问admin/hello,sang用户可以访问user/hello。



