目录
SpringSecurity概括
Spring Security 是一个高度自定义的安全框架。利用 Spring IoC/DI 和 AOP 功能,为系统提供了声明式安全访问控制功能,减少了为系统安全而编写大量重复代码的工作。
使用 Spring Secruity 的原因有很多,主要负责的两个主要区域是“认证”和“授权”(或者访问控制)。这两点是 Spring Security 重要核心功能。“认证”,是建立一个他声明的主体的过程(一个“主体”一般是指用户,设备或一些可以在你的应用程序中执行动作的其他系统),就是系统认为用户是否能登录。“授权”指确定一个主体是否允许在你的应用程序执行一个动作的过程。就是系统判断用户是否有权限去做某些事情。
创建SpringSecurity项目
1.导入依赖
Spring Security已经在Spring Boot集成,添加web和security启动器,直接引用启动器
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>xysh-parent</artifactId>
<groupId>com.xiaobai</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>xysh-system</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.xiaobai</groupId>
<artifactId>xysh-common</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</project>
2.测试
启动SpringBoot项目
访问localhost:8080/login
导入 spring-boot-starter-security 启动器后,Spring Security 已经生效,默认拦截全部请求,如果用户没有登录,跳转到内置登录页面,就是上面这个默认的 username 为 user,password 打印在控制台中,登录成功才可访问login。
设置用户名和密码
当什么也没有配置的时候,账号和密码是由 Spring Security 定义生成的。
而在实际项目中账号和密码都是从数据库中查询出来的,就可以自定义逻辑控制认证逻辑。
如果需要自定义逻辑时,需要实现 UserDetailsService 接口,接口定义如下:
@Service
public class UserDetailsServiceZ implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
return null;
}
}
用户名应该是客户端传递过来的用户名。而密码应该是从数据库中查询出来的密码。Spring Security 会根据 User 中的 password和客户端传递过来的 password 进行比较。如果相同则表示认证通过,如果不相同表示认证失败。
PasswordEncoder密码解析器
Spring Security 要求容器中必须有 PasswordEncoder 实例。
当自定义登录逻辑时要求必须给容器注入 PaswordEncoder 的 bean 对象。
实例代码:
public class MyPasswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence rawPassword) {
return PasswordUtils.generate((String)rawPassword);
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return PasswordUtils.verify((String) rawPassword,encodedPassword);
}
}
接口介绍:
- encode():把参数按照特定的解析规则进行解析。
- matches()验证从存储中获取的编码密码与编码后提交的原始密码是否匹配。如果密码匹配,则返回 true;如果不匹配,则返回 false。
- 第一个参数表示需要被解析的密码。第二个参数表示存储的密码。
- upgradeEncoding():如果解析的密码能够再次进行解析且达到更
- 安全的结果则返回 true,否则返回 false。默认返回 false。
内置解析器介绍:
Spring Security内置了很多解析器
推荐使用:BCryptPasswordEncoder
- BCryptPasswordEncoder 也是 Spring Security 官方推荐的密码解析器,使用这个解析器较多。
- BCryptPasswordEncoder 是对 bcrypt 强散列方法的具体实现。
- 是基于 Hash 算法实现的单向加密。可以通过 strength 控制加密强度,默认 10.
自定义登录逻辑
1.编写配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class SecurityConfig {
@Bean
public PasswordEncoder setPasswordEncoder(){
return new BCryptPasswordEncoder();
}
}
2.自定义逻辑
实现 UserDetailService 就表示为用户详情服务
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private PasswordEncoder encoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
{
//1.查询数据库判断用户名是否存在,如果不存在抛出UsernameNotFoundException
if(!username.equals("admin")){
throw new UsernameNotFoundException("用户名不存在!");
}
//把查询出来的密码进行编码,或直接把password(已经编码好的了)放到构造方法中。
//password就是数据库中查询出来的密码,查询出来的内容不是123,因为数据库不能明文保存数据
String password = encoder.encode("123");
return new User(username,password, AuthorityUtils.
}
}