SpringBoot集成SpringSecurity入门到精通
Springboot环境搭建
- 1.pom文件
<?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>
<groupId>org.example</groupId>
<artifactId>SpringBootText</artifactId>
<version>1.0-SNAPSHOT</version>
<!--springboot版本-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
</parent>
<dependencies>
<!--springboot项目添加web包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--springboot集成测试包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--springboot集成前端thymeleaf框架 有了这个框架就能设置前后缀直接跳转到指定页面-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--权限控制 spring security依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 2.配置文件
application.properties
#更改项目端口号
server.port=8081
# 定位thymeleaf模板的目录 使用@controller直接返回就会找这个模板下面的页面
spring.thymeleaf.prefix=classpath:/templates/
-
3.启动类和controller层
图片.png
-
4.启动
启动访问本地localhost:8080/xxx进行访问就能看到
使用SpringSecurity
-
1.项目搭建完毕开始加入SpringSecurity框架进行权限校验,首先明白它可以为我们是什么
Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
-
2.使用
只需要加入SpringSecurity的依赖就可以了,加入了SpringSecurity再次启动项目进行访问就能看到SpringSecurity框架给我们提供的他们写的登录页面账户名默认是user密码会生成在控制台,进行输入成功后方可进行资源访问.
-
3.迭代1自定义登录页面
自定义登录失败后的友好提示页面和登录页面
首先 添加一个类 SecurityConfig 继承 WebSecurityConfigurerAdapter ,重写configure方法。
加上@Configuration(标明是配置类) 和@EnableWebSecurity (开启)2个注解。
@Override
protected void configure(HttpSecurity http) throws Exception {
//表单登录,permitAll()表示这个不需要验证 登录页面,登录失败页面
/*loginPage("/login") 当目标请求过来访问我们的资源路径跳转到自己写的登录页面
登录页面的 form的提交资源目录就是 loginProcessingUrl("/login/form")
这个是框架校验自己用户名密码的地方如果用户输入的账号密码和框架提供的账号密码不一致就会走failureUrl("/login-error")这个资源路径
跳转到错误页面 , 用户账户密码都输入成功 则会成功成功访问资源路径进行放行
*/
http
.formLogin().loginPage("/login").loginProcessingUrl("/login/form").failureUrl("/login-error").permitAll()
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.csrf().disable();
}
图片.png
再次进行访问项目,看到的就是自己写的登录页面 但是要注意的是表单的提交路径必须和设置的loginProcessingUrl("/login/form")路径一致!!!
-
4.迭代2自定义用户名和密码
按理来说只需要重写configure方法即可
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//设置withUser:用户名 password:密码 roles:角色
auth
.inMemoryAuthentication()
.withUser("admin1").password("123456").roles("USER")
.and()
.withUser("test").password("test123").roles("ADMIN");
}
再次启动项目使用自定义的用户名和密码进行访问会发现一个报错问题:
java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
解决方法:
这是因为Spring boot 2.0.3引用的security 依赖是 spring security 5.X版本,spring security5.x 新增了加密方式 如果重写如重写 configure(AuthenticationManagerBuilder auth)时仍使用该处原代码,会出现如下报错: There is no PasswordEncoder mapped for the id “null” :
(第一种方法 :)
因此,需要创建PasswordEncorder的实现类。MyPasswordEncoder.class:
package com.tang.Money;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
@Component //(记住一定要加这个注解,把这个类交给sprig管理)
public class MyPasswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return s.equals(charSequence.toString());
}
}
再次启动进行访问就能看到不会爆错了,而且能登录成功!!!
但是有人表示需要加上 new MyPasswordEncoder()才算是进行明文密码校验,如下代码 ,但是反复测试只需要将MyPasswordEncoder类交给spring去管理就可以解决此问题
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//可以设置内存指定的登录的账号密码,指定角色
//不加.passwordEncoder(new MyPasswordEncoder())
//就不是以明文的方式进行匹配,会报错
auth.inMemoryAuthentication().withUser("admin").password("123456").roles("ADMIN");
//.passwordEncoder(new MyPasswordEncoder())。
//这样,页面提交时候,密码以明文的方式进行匹配。 new MyPasswordEncoder() 这个类
auth.inMemoryAuthentication().passwordEncoder(new MyPasswordEncoder()).withUser("cxh").password("cxh").roles("ADMIN");
}
(第二种方式:)更改configure重写的源码就不需要注入MyPasswordEncoder这个类了.
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
/* auth
.inMemoryAuthentication()
.withUser("admin1").password("123456").roles("USER")
.and()
.withUser("test").password("test123").roles("ADMIN");*/
auth.
inMemoryAuthentication()
.passwordEncoder(new BCryptPasswordEncoder())
.withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("ADMIN")
.and()
.withUser("test").password(new BCryptPasswordEncoder().encode("test123")).roles("USER");
}