SpringSecurity跟SpringBoot的整合-项目创建

SpringSecurity跟SpringBoot的整合
好想每次都想写系列文章,总是被各种事情打乱,然后就忘记了。在我的草稿箱里,还躺着其他的系列文章,哈哈。
希望这个系列可以写完吧。
创建一个Maven项目
这里就不说创建了,就把pom.xml贴出来吧
<?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">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
<groupId>net.sunofbeach</groupId>
<artifactId>springsecuritydemo</artifactId>
<version>1.0-SNAPSHOT</version>
<name>sob-security-demo</name>
<url>https://www.sunofbeach.net</url>
<inceptionYear>2020-Now</inceptionYear>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<version>1.9.22</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<build>
<finalName>sob-security-demo-1.0.0</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>net.sunofbeach.security.App</mainClass>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
</build>
</project>
把这里的依赖复制粘贴到你的项目里吧
主app程序
package net.sunofbeach.security;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
然后创建测试的controller,security包,分别放置controller和security相关的配置文件之类的
配置登录方式
当我们在依赖里添加了spring-security的依赖(坐标)
导入以后,运行程序,就会被拦截所有的请求
跳转到登录页面
从log上可以看到登录密码
我们打开网页时,比如说我的controller里配置了一个index的页面
我要访问这个页面,就会跳转到登录了
package net.sunofbeach.security.security;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
//拦截所有
.antMatchers("/**")
.fullyAuthenticated()
.and()
//.httpBasic();
.formLogin();
}
}
这里我改成了formLogin,也就是表单登录方式
再跑一次,变成这个样子了
配置账号密码
我覆写了另外一个方法
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(new MyPasswordEncoder())
.withUser("test")
.password("123456")
.authorities("admin");
}
这个就是添加一个硬编码的用户,后面我们要动态地从数据中查询出来
这个MyPasswordEncoder是继承自BCryptPasswordEncoder
代码如下:
package net.sunofbeach.security.security;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
public class MyPasswordEncoder extends BCryptPasswordEncoder {
@Override
public String encode(CharSequence rawPassword) {
return rawPassword.toString();
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return encodedPassword.equals(rawPassword.toString());
}
}
也就是没有进行加密行为,是明文。
这个时候我们再设置一下,登录成功以后,跳转到什么页面
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
//拦截所有
.antMatchers("/**")
.fullyAuthenticated()
.and()
//.httpBasic();
.formLogin()
.defaultSuccessUrl("/index");
}
登录成功以后,跳转到首页去
如何根据权限判断是否放行呢?
先整些用户
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//添加一个注册会员用户
auth.inMemoryAuthentication()
.passwordEncoder(new MyPasswordEncoder())
.withUser("test")
.password("123456")
.authorities("register");
//添加一个管理员帐户
auth.inMemoryAuthentication().passwordEncoder(new MyPasswordEncoder())
.withUser("admin")
.password("admin")
.authorities("register", "admin");
}
然后配置规则
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
//拦截所有
.antMatchers("/manager").hasAuthority("admin")//admin 角色才可以访问
.antMatchers("/list").hasAuthority("register")//注册用户就可以访问
.antMatchers("/**")
.fullyAuthenticated()
.and()
//.httpBasic();
.formLogin()
.defaultSuccessUrl("/index");
}
运行,登录,访问
我们使用test帐户时,访问list是正常的,访问manager则会报错 403,权限不足的错误
但是,我们总不能让用户跑到403界面吧?
所以我们是不是要跳转到自定义的界面呢?我们自己写一个权限不足的页面
处理错误状态码
比如说403,我们总不能让用户看到403页面吧
应该写一个提示权限不足的页面
有些同学可能知道EmbeddedServletContainerCustomizer,但是自从spring boot2.0以上的版本
我们实现这个接口来配置错误页面ErrorPageRegistrar
所以我们接下来应该这么写
@Configuration
public class MyErrorPage implements ErrorPageRegistrar {
@Override
public void registerErrorPages(ErrorPageRegistry registry) {
registry.addErrorPages(new ErrorPage(HttpStatus.FORBIDDEN, "/403"));
}
}
这个addErrorPages,参数是不定参数,可以有多个,如果你要处理各种http状态,就可以使用这个啦。
处理结果:
总结
我们完成了哪些工作呢?
- SpringBoot项目创建
- 自定义登录方式(httpBasic,formLogin)
- 添加硬编码用户测试
- 权限根据角色控制
- 自定义错误页面
后面我们再去自定义登录界面吧,在下一篇文章再去从数据库中获取用户信息和用户角色。