SpringSecurity 安全框架
入门案例
创建基于maven环境的springboot2项目。并引入相关的依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<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>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
新建controller包并创建测试用的controller类TestController
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author ChenRuXu
* @Date 2023/2/17 19:50
* @Version 1.0
*/
@RestController
@RequestMapping("/test")
public class TestController {
@GetMapping("/hello")
public String add(){
return "hello security";
}
}
访问页面时出现了默认的安全认证窗口,密码在控制台处进行显示。默认的用户名为user
基本原理
springsecurity本质上是一个过滤器链
FilterSecurityInterceptor过滤器
位于最低端的过滤器是一个方法级的权限过滤器。
public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
private static final String FILTER_APPLIED = "__spring_security_filterSecurityInterceptor_filterApplied";
private FilterInvocationSecurityMetadataSource securityMetadataSource;
private boolean observeOncePerRequest = true;
该类实现了Filter接口是一个过滤器类
public interface Filter {
default void init(FilterConfig filterConfig) throws ServletException {
}
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
default void destroy() {
}
过滤器接口实现了三个方法包括了,init初始化过滤器执行的方法,doFilter过滤时执行的方法,和销毁时执行的方法。
ExceptionTranslationFilter过滤器
是个异常处理的过滤器用来处理在认证授权的过程中抛出的异常信息。
public class ExceptionTranslationFilter extends GenericFilterBean implements MessageSourceAware {
private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
chain.doFilter(request, response);
} catch (IOException var7) {
throw var7;
} catch (Exception var8) {
Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(var8);
RuntimeException securityException = (AuthenticationException)this.throwableAnalyzer.getFirstThrowableOfType(AuthenticationException.class, causeChain);
if (securityException == null) {
securityException = (AccessDeniedException)this.throwableAnalyzer.getFirstThrowableOfType(AccessDeniedException.class, causeChain);
}
if (securityException == null) {
this.rethrow(var8);
}
if (response.isCommitted()) {
throw new ServletException("Unable to handle the Spring Security Exception because the response is already committed.", var8);
}
this.handleSpringSecurityException(request, response, chain, (RuntimeException)securityException);
}
}
处理各种异常的信息。
UsernamePasswordAuthenticationFilter过滤器
UsernamePasswordAuthenticationFilter过滤器:对/login的POST请求做拦截,校验表单中用户名密码。
核心的业务逻辑
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (this.postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
} else {
String username = this.obtainUsername(request);
username = username != null ? username.trim() : "";
String password = this.obtainPassword(request);
password = password != null ? password : "";
UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username, password);
this.setDetails(request, authRequest);
return this.getAuthenticationManager().authenticate(authRequest);
}
}
过滤器链的加载过程
使用springsecurity配置过滤器
需要配置的过滤器为:DelegatingFilterProxy
public class DelegatingFilterProxy extends GenericFilterBean {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
Filter delegateToUse = this.delegate;
if (delegateToUse == null) {
synchronized(this.delegateMonitor) {
delegateToUse = this.delegate;
if (delegateToUse == null) {
WebApplicationContext wac = this.findWebApplicationContext();
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener or DispatcherServlet registered?");
}
delegateToUse = this.initDelegate(wac);
}
this.delegate = delegateToUse;
}
}
}
使用this.initDelegate(wac)进行初始化加载需要需要用到的信息
转载:https://blog.csdn.net/weixin_46167190/article/details/129093805
查看评论