- spring security简介
- 什么是spring security
- spring security 核心功能
- spring security 原理
- spring security实例
- 初探spring security
- 使用内存中的用户信息
- 基于角色 Role 的身份认证
spring security 是基于 spring 的安全框架。它提供全面的安全性解决方案,同时在 Web 请求级和方法调用级处理身份确认和授权。在 Spring framework 基础上,spring security 充分利用了依赖注入(DI)和面向切面编程(AOP)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。是一个轻量级的安全框架。它与 Spring MVC 有很好地集成.
spring security 核心功能(1)认证(你是谁,用户/设备/系统)
(2)验证(你能干什么,也叫权限控制/授权,允许执行的操作)。
基于 Filter , Servlet, AOP 实现身份认证和权限验证
spring security实例 初探spring security- 创建 maven 项目
- 加入依赖:spring boot 依赖, spring security 依赖
org.springframework.boot spring-boot-parent 2.0.6.RELEASE org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-security
- 创建 Controller,接收请求
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping()
public class HelloSecurityController {
@RequestMapping("/test1")
@ResponseBody
public String sayHello() {
return "Hello Spring Secuirty 安全管理框架";
}
}
-
框架生成的用户
用户名: user
密码: 在启动项目时,生成的临时密码。uuid
日志中生成的密码
generated security password: 9717464c-fafd-47b3-9995-2c18b24f7336 -
自定义用户名和密码
需要在 springboot 配置文件中设置登录的用户名和密码
在 resource 目录下面创建 spring boot 配置文件
application.yml(application.properties)security: user: name: Nick password: Nickname:自定义用户名称
password:自定义密码
-
关闭验证
//排除Security的配置,让他不启用 @SpringBootApplication(exclude = {SecurityAutoConfiguration.class}) //@SpringBootApplication public class SercurityTest1Application { public static void main(String[] args) { SpringApplication.run(SercurityTest1Application.class, args); } }
使用内存中的用户信息是指在服务器的内存中简单的配置用户信息,进行权限相应的配置,可以更灵活的进行功能测试,并没有使用数据库。
1)使用:WebSecurityConfigurerAdapter 控制安全管理的内容。
需要做的使用:继承 WebSecurityConfigurerAdapter,重写方法。实现
自定义的认证信息。重写下面的方法。
protected void configure(AuthenticationManagerBuilder auth)
2)spring security 5 版本要求密码进行加密,否则报错
java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
实现密码加密:
- 创建用来加密的实现类(选择一种加密的算法)
@Bean
public PasswordEncoder passwordEncoder(){
//创建 PasawordEncoder 的实现类, 实现类是加密算法
return new BCryptPasswordEncoder();
}
- 给每个密码加密
PasswordEncoder pe = passwordEncoder();
pe.encode("123456")
3)示例代码如下
package cn.kt.sercurity_test1.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
public class MySecurityConfig {
//在方法中配置用户和密码的信息、作为登录信息
//定义两个角色 normal admin
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
PasswordEncoder pe = passwordEncoder();
auth.inMemoryAuthentication().withUser("admin").password(pe.encode("admin")).roles();
auth.inMemoryAuthentication().withUser("Nick").password(pe.encode("Nick")).roles();
auth.inMemoryAuthentication().withUser("Amy").password(pe.encode("Amy")).roles();
}
//创建密码的加密类
@Bean
public PasswordEncoder passwordEncoder() {
//创建PasswordEncoder的实现类,实现类是加密算法
return new BCryptPasswordEncoder();
}
}
注解:
- @Configuration :表示当前类是一个配置类(相当于是 spring 的 xml
配置文件),在这个类方法的返回值是 java 对象,这些对象放入到
spring 容器中。 - @EnableWebSecurity:表示启用 spring security 安全框架的功能
- @Bean:把方法返回值的对象,放入到 spring 容器中。
基于角色的实现步骤:
1、设置用户的角色
继承 WebSecurityConfigurerAdapter
重写 configure 方法。指定用户的 roles
auth.inMemoryAuthentication().withUser("admin").password(pe.encode("admin")).roles("admin","normal");
2、在类的上面加入启用方法级别的注解
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
}
加上@EnableGlobalMethodSecurity(prePostEnabled = true)注解之后在方法层面,就可以手动使用使用@PreAuthorize 指定在方法之前进行角色的认证,指定方法可以访问的角色列表。
如:hasAnyRole(‘角色名称 1’,‘角色名称 N’);
package cn.kt.sercurity_test1.controller;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AuthorizeSecurityController {
//指定 normal和admin都可以访问的通用的方法
@RequestMapping("/testUser")
@PreAuthorize(value = "hasAnyRole('admin','normal')")
public String testUser() {
return "Hello Spring Secuirty normal和admin都可以访问的通用的方法";
}
//指定 admin访问的专有的方法
@RequestMapping("/testAdmin")
@PreAuthorize(value = "hasAnyRole('admin')")
public String testAdmin() {
return "Hello Spring Secuirty admin访问的专有的方法";
}
}
3、或者在配置类中,进行权限的统一配置
如以下编写的配置类:
package cn.kt.securitytest2.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
// @EnableWebSecurity已经自动导入了配置注解@Configuration,可以不不用重复添加
@EnableWebSecurity
public class MySecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//super.configure(http);
//定制请求的授权规则
http.authorizeRequests().antMatchers("/").permitAll()
.antMatchers("/level1*.html",
"*.css",
"*.js",
"/webSocket/**"
).permitAll();
}
//定义认证规则
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//super.configure(auth);
PasswordEncoder pe = passwordEncoder();
auth.inMemoryAuthentication()
.withUser("zhangsan").password(pe.encode("123456")).roles("VIP1", "VIP2")
.and()
.withUser("lisi").password(pe.encode("123456")).roles("VIP2", "VIP3")
.and()
.withUser("wangwu").password(pe.encode("123456")).roles("VIP1", "VIP3");
}
//创建密码的加密类
@Bean
public PasswordEncoder passwordEncoder() {
//创建 PasawordEncoder 的实现类, 实现类是加密算法
return new BCryptPasswordEncoder();
}
}
注意:
- 重写protected void configure(HttpSecurity http) throws Exception {}方法进行权限的授权控制
- http.authorizeRequests().antMatchers("/").permitAll()表示所有人可以访问”/“首页;http.authorizeRequests().antMatchers("/level1/**").hasRole(“VIP1”)表示只有有"VIP1"权限的人,才可以访问”/level1/xxx"页面下的内容。相应的很有必要添加静态资源不需要授权。
- http.formLogin()开启自动配置的登陆功能,效果:如果没有登陆,没有权限就会来到登陆页面,相应的也可以按照代码中的注释来自定义登录规则
- http.logout().logoutSuccessUrl("/")开启自动配置的注销功能,注销成功以后来到首页,并且清空session
- http.rememberMe()开启记住我功能,会将cookie发给浏览器保存,以后访问页面带上这个cookie,只要通过检查就可以免登录



