Spring Security
spring security目的:验证,授权,攻击防护。
spring security原理:创建大量的filter和interceptor来进行请求的验证和拦截,以此来达到安全的效果。
spring security本质:是一个过滤链,有很多过滤器
FilterSecurityInterceptor:访问授权,是一个方法级的权限过滤器,基本位于过滤器的最底部;
ExceptionTranslationFilter:异常过滤器,处理在认证过程中抛出的异常;
UsernamePasswordAuthenticationFilter:基于用户名和密码的身份验证过滤器,对/login的POST请求做拦截,校验表单中用户名、密码;
UserDetailsService:可以通过loadUserByUsername获取UserDetails对象。该接口供spring security进行用户验证。通常使用自定义一个CustomUserDetailsService来实现UserDetailsService接口,通过自定义查询UserDetails。【查询数据库用户名和密码过程】
AuthenticationManager:用来进行验证,如果验证失败会抛出相对应的异常*
PasswordEncoder:密码加密器
BCryptPasswordEncoder:哈希算法加密
NoOpPasswordEncoder:不使用加密
WebSecurityConfigurerAdapter:
AuthenticationManagerBuilder:
JwtAuthenticationFilter:登录认证检查过滤器
JwtLoginFilter:登录认证过滤器
LogoutFilter:登出过滤器
ResourceServerConfigurerAdapter:资源认证服务配置
AuthorizationServerSecurityConfigurer:授权认证服务配置
*
*
TokenLoginFilter
TokenAuthFilter
BasicAuthenticationFilter
*
*
1、pom.xml 文件中添加依赖
spring-boot-starter-web
spring-boot-starter-security
jjwt
fastjson
4.0.0 org.springframework.boot spring-boot-starter-parent2.6.3 com.example demoSecurity0.0.1-SNAPSHOT demoSecurity demoSecurity 11 org.springframework.boot spring-boot-starter-weborg.springframework.boot spring-boot-starter-securityio.jsonwebtoken jjwt0.9.1 com.alibaba fastjson1.2.62 org.springframework.boot spring-boot-starter-testtest org.springframework.security spring-security-testtest org.springframework.boot spring-boot-maven-plugin
2、添加一个TestController【使用默认用户和随机生成的密码登录】
package com.example.demos.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("hello")
public String hello() {
return "hello";
}
}
启动项目,这样在启动的时候会在控制台显示随机生成的密码
spring security 默认的用户名是user,启动的时候会在控制台显示随机生成的密码
访问http://localhost:8080/test/hello
重定向到http://localhost:8080/login,这个页面是spring默认的
填入user 和 上图显示的81b60805-e799-4596-a404-17616dc56ecf,那么就会正常的访问/test/hello接口
*
3、配置文件,使用yml文件定义的用户名、密码登录【配置文件】
spring:
security:
user:
name: root
password: root
输入root/root登录,可以正常访问/test/hello接口
*
4、配置类,实现用户名、密码登录【配置类】
新建 config 包,新建 SecurityCofig.java 文件
package com.example.demos.config;
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.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.net.PasswordAuthentication;
@Configuration
public class SecurityCofig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
BCryptPasswordEncoder passwordEncoder=new BCryptPasswordEncoder();
String password = passwordEncoder.encode("123456");
auth.inMemoryAuthentication().withUser("admin").password(password).roles("");
}
@Bean
PasswordEncoder password(){
return new BCryptPasswordEncoder();
}
}
输入admin/123456登录,可以正常访问/test/hello接口
*
5、自定义实现类【UserDetailsService】
在 config 包,新建 MySecurityConfiguration.java 文件
package com.example.demos.config;
import org.springframework.beans.factory.annotation.Autowired;
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.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
public class MySecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(password());
}
@Bean
PasswordEncoder password(){
return new BCryptPasswordEncoder();
}
}
新建 service 包,新建 MyUserDetailsService.java 文件
package com.example.demos.service;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.GrantedAuthority;
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import java.util.List;
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//可以查询数据库
List authorities = AuthorityUtils.commaSeparatedStringToAuthorityList("role");
return new User("admin",new BCryptPasswordEncoder().encode("123123"),authorities);
}
}
输入admin/123123登录,可以正常访问/test/hello接口
*
2、配置文件
跨域配合文件:CorsConfig.java
接口生成文件:SwaggerConfig.java
安全配置文件:WebSecurityConfig.java
2.1、CorsConfig.java 跨域配置
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").
allowedOrigins("https://www.***.com"). //允许跨域的域名,可以用*表示允许任何域名使用
allowedMethods("GET", "POST", "DELETE", "PUT").
//allowedMethods("*"). //允许任何方法(post、get等)
allowCredentials(true). //带上cookie信息
allowedHeaders("*"). //允许任何请求头
maxAge(3600).
exposedHeaders(HttpHeaders.SET_cookie).maxAge(3600L); //maxAge(3600)表明在3600秒内,不需要再发送预检验请求,可以缓存该结果
}
}
2.2、SwaggerConfig.java
*
*
*
2.3、WebSecurityConfig.java
*
*
*
*
*
*
*



