一、UserDetails接口介绍
SpringSecurity通过UserDetail对象来管理用户
UserDetail有一个实现类User,我们需要将数据库中得到的用户信息包装成User类的实例,然后才能让SpringSecurity来管理用户的认证鉴权。
二、引入Maven依赖
<dependencies>
<!--SpringSecurity启动依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--Web启动依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--Mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--数据库访问框架JPA-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
</dependencies>
三、创建entity、dao、service
entity代码:
//表示当前类是一个实体类,表示数据库中的一个表
//表名默认和类名一样
@Entity
public class UserInfo {
@Id//主键
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String username;
private String passwored;
private String role;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPasswored() {
return passwored;
}
public void setPasswored(String passwored) {
this.passwored = passwored;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
dao代码:
使用了jpa数据库访问框架
public interface UserInfoDao extends JpaRepository<UserInfo, Long> {
//按照username查询数据库信息
UserInfo findByUsername(String username);
}
service代码:
public interface UserInfoService {
UserInfo findUserInfo(String username);
}
@Service
public class UserInfoServiceImpl implements UserInfoService {
@Autowired
UserInfoDao userInfoDao;
@Override
public UserInfo findUserInfo(String username) {
UserInfo userInfo = userInfoDao.findByUsername(username);
return userInfo;
}
}
springboot核心配置文件:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springsecurity?useUnicode=true&characterEnconding=UTF-8
spring.datasource.username=root
spring.datasource.password=123456
#jpa相关配置
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
spring.jpa.database=mysql
启动项目,此时jpa组件就会创建UserInfo实体类对应的数据库表
数据库信息初始化:
@Component
public class JdbcInit {
@Autowired
private UserInfoDao userInfoDao;
@PostConstruct
public void init(){
PasswordEncoder encoder = new BCryptPasswordEncoder();
UserInfo userInfo = new UserInfo();
userInfo.setUsername("zhangsan");
userInfo.setPasswored(encoder.encode("123456"));
userInfo.setRole("normal");
userInfoDao.save(userInfo);
userInfo = new UserInfo();
userInfo.setUsername("admin");
userInfo.setPasswored(encoder.encode("123456"));
userInfo.setRole("admin");
userInfoDao.save(userInfo);
}
}
四、实现UserDetailsService接口
自定义一个类实现UserDetailService接口,从数据库中读取用户信息,传给SpringSecurity的User对象并返回。
@Component("MyUserDetailService")
public class MyUserDetailService implements UserDetailsService {
@Autowired
private UserInfoDao userInfoDao;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = null;
UserInfo userInfo = null;
if (username != null) {
userInfo = userInfoDao.findByUsername(username);
if (userInfo != null) {
List<GrantedAuthority> list = new ArrayList<>();
//角色必须以ROLE_开头
GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_" + userInfo.getRole());
list.add(authority);
//创建User对象
user = new User(userInfo.getUsername(), userInfo.getPasswored(), list);
}
}
return user;
}
}
五、在配置类中配置
@Configuration//表示当前类是一个配置类,在这个类中方法的返回值是java对象,这些对象放入到Spring容器中
@EnableWebSecurity//启用SpringSecurity安全框架的功能
@EnableGlobalMethodSecurity(prePostEnabled = true)//启用方法级别的认证 prePostEnabled=true表示可以使用@PreAuthorize和@PostAuthrize
public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("MyUserDetailService")
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
}
六、controller层,在方法上使用注解
@Controller
public class HelloController {
@RequestMapping("/hello")
@ResponseBody
public String hello(){
return "Hello SpringSecurity";
}
//normal,admin都可以访问
@RequestMapping("/helloUser")
@ResponseBody
@PreAuthorize(value = "hasAnyRole('admin','normal')")
public String helloCommonUser(){
return "Hello user";
}
//admin才能访问
@RequestMapping("/helloAdmin")
@ResponseBody
@PreAuthorize(value = "hasAnyRole('admin')")
public String helloAdmin(){
return "Hello admin";
}
}