SpringSecurity常见配置操作
UserDetailsService详解
当什么也没有配置的时候,账号和密码是由 Spring Security 定义生成的。而在实际项目中账号和密码都是从数据库中查询出来的。所以我们要通过自定义逻辑控制认证逻辑。如果需要自定义逻辑时,只需要实现 UserDetailsService 接口即可。接口定义如下:
- UserDetailsService认证接口,里面提供了一个方法loadUserByUsername(String username);这个接口是开发者自己去实现和控制的
- 实现步骤1,根据用户名去查询用户
- 实现步骤2,根据用户名去查询对应的角色
- 实现步骤3,根据用户名去查询对应的权限
- 实现步骤4,把查询出来的用户信息和角色信息和权限信息,放入到一个User对象即可
- 实现步骤5,SprignSecurity初始化工作就完成了。
- 实现步骤6,用户请求资源,就会根据你请求的资源的权限去User里面查看有没对应的角色或者权限,如果有有就进行放行,如果没有就报错403.没有权限访问。
从Spring5以后开始强制使用密码加密访问。SpringSecurity提供了BCryptPasswordEncoder密码编码工具,可以非常方便地实现密码的加密和加盐处理,相同的明文加密出来的结果总是不同,这样就不需要用户去额外保存盐的字段了。
新建测试方法BCryptPasswordEncoder 用法。
package com.yjxxt.springsecuritydemo;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* @author zhoubin
* @since 1.0.0
*/
@SpringBootTest
public class MyTest {
@Test
public void test(){
//创建解析器
PasswordEncoder pw = new BCryptPasswordEncoder();
//对密码加密
String encode = pw.encode("123");
System.out.println(encode);
//判断原字符和加密后内容是否匹配
boolean matches = pw.matches("1234", encode);
System.out.println("==================="+matches);
}
}
在 Spring Security 中实现 UserDetailService 就表示为用户详情服务。在这个类中编写用户认证逻辑。
package com.yjxxt.springsecuritydemo.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.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.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
/**
* @author zhoubin
* @since 1.0.0
*/
@Service
public class UserServiceImpl implements UserDetailsService {
@Autowired
private PasswordEncoder pw;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//1.查询数据库判断用户名是否存在,如果不存在抛出UsernameNotFoundException异常
if (!"admin".equals(username)){
throw new UsernameNotFoundException("用户名不存在");
}
//2.把查询出来的密码(注册时已经加密过)进行解析,或直接把密码放入构造方法中
String password = pw.encode("123");
return new User(username,password, AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal"));
}
}
有很多坑需要琢磨
两种写法,一个要写前缀,一个不用写前缀~!
gitee的流程思路