• Spring Security6 用户身份认证


    前提

    1.  你需要先拜读 [Spring Security 6 官方文档](https://docs.spring.io/spring-security/reference/servlet/authentication/architecture.html#servlet-authentication-authenticationmanager)
    2.  你需要弄清楚身份认证(Authentication)和鉴权(Authorization)是两个概念,其中本文只涉及身份认证

    身份认证需要做哪些事情

    1. 要弄清楚每次请求,客户端的具体身份是谁
    2. 根据不同的接口类型,启用不同的认证机制

    Show me your code

    • 添加 POM.xml
    1. "1.0" encoding="UTF-8"?>
    2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    4. <modelVersion>4.0.0modelVersion>
    5. <parent>
    6. <groupId>org.springframework.bootgroupId>
    7. <artifactId>spring-boot-starter-parentartifactId>
    8. <version>3.1.5version>
    9. <relativePath/>
    10. parent>
    11. <groupId>com.examplegroupId>
    12. <artifactId>demoartifactId>
    13. <version>0.0.1-SNAPSHOTversion>
    14. <name>demoname>
    15. <description>Demo project for Spring Bootdescription>
    16. <properties>
    17. <java.version>21java.version>
    18. properties>
    19. <dependencies>
    20. <dependency>
    21. <groupId>org.springframework.bootgroupId>
    22. <artifactId>spring-boot-starter-securityartifactId>
    23. dependency>
    24. <dependency>
    25. <groupId>org.springframework.bootgroupId>
    26. <artifactId>spring-boot-starter-webartifactId>
    27. dependency>
    28. <dependency>
    29. <groupId>org.springframework.bootgroupId>
    30. <artifactId>spring-boot-starter-testartifactId>
    31. <scope>testscope>
    32. dependency>
    33. <dependency>
    34. <groupId>org.springframework.securitygroupId>
    35. <artifactId>spring-security-testartifactId>
    36. <scope>testscope>
    37. dependency>
    38. dependencies>
    39. <build>
    40. <plugins>
    41. <plugin>
    42. <groupId>org.springframework.bootgroupId>
    43. <artifactId>spring-boot-maven-pluginartifactId>
    44. <configuration>
    45. <image>
    46. <builder>paketobuildpacks/builder-jammy-base:latestbuilder>
    47. image>
    48. configuration>
    49. plugin>
    50. plugins>
    51. build>
    52. project>
    • 自定义过滤器
    1. /**
    2. *
    3. */
    4. package com.example.demo;
    5. import java.io.IOException;
    6. import org.springframework.security.authentication.BadCredentialsException;
    7. import org.springframework.security.authentication.InternalAuthenticationServiceException;
    8. import org.springframework.security.authentication.ProviderManager;
    9. import org.springframework.security.core.Authentication;
    10. import org.springframework.security.core.AuthenticationException;
    11. import org.springframework.security.core.context.SecurityContextHolder;
    12. import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
    13. import org.springframework.security.web.util.matcher.RequestMatcher;
    14. import jakarta.servlet.FilterChain;
    15. import jakarta.servlet.ServletException;
    16. import jakarta.servlet.ServletRequest;
    17. import jakarta.servlet.ServletResponse;
    18. import jakarta.servlet.http.HttpServletRequest;
    19. import jakarta.servlet.http.HttpServletResponse;
    20. /**
    21. *
    22. */
    23. public class AuthenticationBuilderFilter extends AbstractAuthenticationProcessingFilter {
    24. protected AuthenticationBuilderFilter() {
    25. super(new RequestMatcher() {
    26. @Override
    27. public boolean matches(HttpServletRequest request) {
    28. return true;
    29. }
    30. });
    31. super.setAuthenticationManager(new ProviderManager(new WebAuthenticationProvider()));
    32. }
    33. @Override
    34. public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
    35. throws AuthenticationException, IOException, ServletException {
    36. Authentication auth = new WebAuthentication(request);
    37. return getAuthenticationManager().authenticate(auth);
    38. }
    39. @Override
    40. public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
    41. throws IOException, ServletException {
    42. HttpServletRequest request = (HttpServletRequest) req;
    43. HttpServletResponse response = (HttpServletResponse) res;
    44. if (!requiresAuthentication(request, response)) {
    45. chain.doFilter(request, response);
    46. return;
    47. }
    48. try {
    49. Authentication authenticationResult = attemptAuthentication(request, response);
    50. if (authenticationResult == null) {
    51. throw new BadCredentialsException("没有身份信息");
    52. }
    53. SecurityContextHolder.getContext().setAuthentication(authenticationResult);
    54. chain.doFilter(request, response);
    55. }
    56. catch (InternalAuthenticationServiceException failed) {
    57. this.logger.error("An internal error occurred while trying to authenticate the user.", failed);
    58. unsuccessfulAuthentication(request, response, failed);
    59. }
    60. catch (AuthenticationException ex) {
    61. // Authentication failed
    62. unsuccessfulAuthentication(request, response, ex);
    63. }
    64. }
    65. }

    这里有几个地方需要注意(敲黑板啦~~

    1. 第 37 行,可以根据需要,添加多个provider
    2. 第 43 行,后续可以根据实际需要,构建不同的 Authentication ,框架会根据 Authentication 的类型,选择认证 provider(这个是精髓)
    • 自定义 Authentication —— WebAuthentication,可以在构造函数内自己根据需要(比如从 requestHeader、cookie等地方,获取 token)组装 Authentication
    1. /**
    2. *
    3. */
    4. package com.example.demo;
    5. import java.util.Collection;
    6. import org.springframework.security.core.Authentication;
    7. import org.springframework.security.core.GrantedAuthority;
    8. import jakarta.servlet.http.HttpServletRequest;
    9. /**
    10. *
    11. */
    12. public class WebAuthentication implements Authentication{
    13. public WebAuthentication() {
    14. }
    15. public WebAuthentication(HttpServletRequest request) {
    16. }
    17. /**
    18. *
    19. */
    20. private static final long serialVersionUID = -1705541938861263059L;
    21. @Override
    22. public String getName() {
    23. return null;
    24. }
    25. @Override
    26. public Collectionextends GrantedAuthority> getAuthorities() {
    27. return null;
    28. }
    29. @Override
    30. public Object getCredentials() {
    31. return null;
    32. }
    33. @Override
    34. public Object getDetails() {
    35. return null;
    36. }
    37. @Override
    38. public Object getPrincipal() {
    39. return null;
    40. }
    41. @Override
    42. public boolean isAuthenticated() {
    43. return false;
    44. }
    45. @Override
    46. public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
    47. }
    48. }
    • 写认证逻辑 ,下面例子认证逻辑被我简化了,大家根据实际需要进行补充
    1. /**
    2. *
    3. */
    4. package com.example.demo;
    5. import org.springframework.security.authentication.AuthenticationProvider;
    6. import org.springframework.security.core.Authentication;
    7. import org.springframework.security.core.AuthenticationException;
    8. /**
    9. *
    10. */
    11. public class WebAuthenticationProvider implements AuthenticationProvider {
    12. @Override
    13. public Authentication authenticate(Authentication authentication) throws AuthenticationException {
    14. authentication.setAuthenticated(true);
    15. return authentication;
    16. }
    17. @Override
    18. public boolean supports(Class authentication) {
    19. return authentication.equals(WebAuthentication.class);
    20. }
    21. }
    • 配置过滤链
    1. /**
    2. *
    3. */
    4. package com.example.demo;
    5. import org.springframework.context.annotation.Bean;
    6. import org.springframework.context.annotation.Configuration;
    7. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    8. import org.springframework.security.web.SecurityFilterChain;
    9. import org.springframework.security.web.csrf.CsrfFilter;
    10. /**
    11. *
    12. */
    13. @Configuration
    14. public class SecurityConfig {
    15. @Bean
    16. SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    17. http
    18. .csrf(csrf ->csrf.disable())
    19. .addFilterAfter(new AuthenticationBuilderFilter(), CsrfFilter.class)
    20. ;
    21. return http.build();
    22. }
    23. }

  • 相关阅读:
    VPN简介
    相似度系列—2传统方法BLEU:BLEU: a Method for Automatic Evaluation of Machine Translation
    三、Spring Boot 整合视图层技术
    企业销售额和客户服务有关系吗?
    【杂七杂八】Huawei Gt runner手表系统降级
    Web 安全之时序攻击 Timing Attack 详解
    伙伴云表格强势升级!Pro版,更非凡!
    数据库表设计优化
    Remove和RemoveLast用法
    IS420ESWBH3A GE 附加配置文件和I/O组件中的单独标签
  • 原文地址:https://blog.csdn.net/luyangbin01/article/details/134525284