From d84e26ed4928f0f745a1e36ba65025cafc182f72 Mon Sep 17 00:00:00 2001 From: bamanker <27054792@qq.com> Date: Thu, 15 Jan 2026 17:31:18 +0800 Subject: [PATCH] =?UTF-8?q?=E7=AC=AC=E4=BA=8C=E6=AC=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 49 +++++++++++++++ .../config/SecurityConfig.java | 25 ++++++++ .../controller/HomeController.java | 38 ++++++++++++ .../filter/LoopbackIpRedirectFilter.java | 33 ++++++++++ .../service/CustomUserDetailsService.java | 22 +++++++ .../src/main/resources/application.yml | 61 ++++++++++++++++++- .../config/SecurityConfig.java | 25 ++++++++ .../controller/ApiController.java | 40 ++++++++++++ .../service/CustomUserDetailsService.java | 22 +++++++ .../src/main/resources/application.yml | 9 ++- 10 files changed, 322 insertions(+), 2 deletions(-) create mode 100644 sp4-oauth2-client/src/main/java/com/bamanker/sp4oauth2client/config/SecurityConfig.java create mode 100644 sp4-oauth2-client/src/main/java/com/bamanker/sp4oauth2client/controller/HomeController.java create mode 100644 sp4-oauth2-client/src/main/java/com/bamanker/sp4oauth2client/filter/LoopbackIpRedirectFilter.java create mode 100644 sp4-oauth2-client/src/main/java/com/bamanker/sp4oauth2client/service/CustomUserDetailsService.java create mode 100644 sp4-oauth2-resource-server/src/main/java/com/bamanker/sp4oauth2resourceserver/config/SecurityConfig.java create mode 100644 sp4-oauth2-resource-server/src/main/java/com/bamanker/sp4oauth2resourceserver/controller/ApiController.java create mode 100644 sp4-oauth2-resource-server/src/main/java/com/bamanker/sp4oauth2resourceserver/service/CustomUserDetailsService.java diff --git a/sp4-oauth2-authorization-server/src/main/resources/application.yml b/sp4-oauth2-authorization-server/src/main/resources/application.yml index f6707f8..17e775e 100644 --- a/sp4-oauth2-authorization-server/src/main/resources/application.yml +++ b/sp4-oauth2-authorization-server/src/main/resources/application.yml @@ -1,2 +1,51 @@ server: port: 9000 + + +spring: + application: + name: sp4-oauth2-authorization-server + # 数据源配置(用于存储客户端和授权信息) + datasource: + url: jdbc:h2:mem:oauth2db + driver-class-name: org.h2.Driver + username: sa + password: + jpa: + hibernate: + ddl-auto: create-drop + show-sql: true + # OAuth2授权服务器配置 + security: + # 默认用户(用于授权服务器管理) + user: + name: admin + password: admin123 + roles: ADMIN + oauth2: + authorizationserver: + # 客户端注册配置 + issuer: http://localhost:9000 + client: + login-client: + registration: + client-id: "login-client" + client-secret: "{noop}openid-connect" + client-authentication-methods: + - "client_secret_basic" + authorization-grant-types: + - "authorization_code" + - "refresh_token" + redirect-uris: + - "http://127.0.0.1:8080/login/oauth2/code/login-client" + - "http://127.0.0.1:8080/authorized" + scopes: + - "openid" + - "profile" + - "email" + - "address" + require-authorization-consent: true + +logging: + level: + org.springframework.security: trace \ No newline at end of file diff --git a/sp4-oauth2-client/src/main/java/com/bamanker/sp4oauth2client/config/SecurityConfig.java b/sp4-oauth2-client/src/main/java/com/bamanker/sp4oauth2client/config/SecurityConfig.java new file mode 100644 index 0000000..b65d103 --- /dev/null +++ b/sp4-oauth2-client/src/main/java/com/bamanker/sp4oauth2client/config/SecurityConfig.java @@ -0,0 +1,25 @@ +package com.bamanker.sp4oauth2client.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration +public class SecurityConfig { + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests(authorize -> authorize + .requestMatchers("/admin/**").hasRole("ADMIN") + .anyRequest().authenticated() + ) + .formLogin(Customizer.withDefaults() + ) + .csrf(Customizer.withDefaults()) + .httpBasic(Customizer.withDefaults() + ); + return http.build(); + } +} diff --git a/sp4-oauth2-client/src/main/java/com/bamanker/sp4oauth2client/controller/HomeController.java b/sp4-oauth2-client/src/main/java/com/bamanker/sp4oauth2client/controller/HomeController.java new file mode 100644 index 0000000..e3f1bd0 --- /dev/null +++ b/sp4-oauth2-client/src/main/java/com/bamanker/sp4oauth2client/controller/HomeController.java @@ -0,0 +1,38 @@ +package com.bamanker.sp4oauth2client.controller; + +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.oauth2.client.OAuth2AuthorizedClient; +import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient; +import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +/** + * 测试控制器 + */ +@RestController +public class HomeController { + /** + * 首页 + * 需要认证才能访问 + */ + @GetMapping("/") + public Map home(@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient client, + @AuthenticationPrincipal OAuth2User oauth2User) { + return Map.of( + "message", "欢迎使用OAuth2登录", + "user", oauth2User.getName(), + "client", client.getClientRegistration().getClientName(), + "userAttributes", oauth2User.getAttributes() + ); + } + /** + * 获取当前用户信息 + */ + @GetMapping("/user") + public OAuth2User user(@AuthenticationPrincipal OAuth2User oauth2User) { + return oauth2User; + } +} \ No newline at end of file diff --git a/sp4-oauth2-client/src/main/java/com/bamanker/sp4oauth2client/filter/LoopbackIpRedirectFilter.java b/sp4-oauth2-client/src/main/java/com/bamanker/sp4oauth2client/filter/LoopbackIpRedirectFilter.java new file mode 100644 index 0000000..131e658 --- /dev/null +++ b/sp4-oauth2-client/src/main/java/com/bamanker/sp4oauth2client/filter/LoopbackIpRedirectFilter.java @@ -0,0 +1,33 @@ +package com.bamanker.sp4oauth2client.filter; + +import jakarta.annotation.Nonnull; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.jspecify.annotations.NonNull; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; +import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; + +import java.io.IOException; + +//@Component +//@Order(Ordered.HIGHEST_PRECEDENCE) +public class LoopbackIpRedirectFilter extends OncePerRequestFilter { + @Override + protected void doFilterInternal(HttpServletRequest request, @Nonnull HttpServletResponse response + , @Nonnull FilterChain filterChain) throws ServletException, IOException { + if (request.getServerName().equals("localhost") && request.getHeader("host") != null) { + UriComponents uri = UriComponentsBuilder.fromUriString(request.getRequestURL().toString()) + .host("127.0.0.1") + .build(); + response.sendRedirect(uri.toUriString()); + return; + } + filterChain.doFilter(request, response); + } +} diff --git a/sp4-oauth2-client/src/main/java/com/bamanker/sp4oauth2client/service/CustomUserDetailsService.java b/sp4-oauth2-client/src/main/java/com/bamanker/sp4oauth2client/service/CustomUserDetailsService.java new file mode 100644 index 0000000..d6ab2cd --- /dev/null +++ b/sp4-oauth2-client/src/main/java/com/bamanker/sp4oauth2client/service/CustomUserDetailsService.java @@ -0,0 +1,22 @@ +package com.bamanker.sp4oauth2client.service; + +import org.jspecify.annotations.NonNull; +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.stereotype.Service; + +@Service +public class CustomUserDetailsService implements UserDetailsService { + @Override + public UserDetails loadUserByUsername(@NonNull String username) throws UsernameNotFoundException { + if ("admin".equals(username)) { + return User.withUsername("admin") + .password("{noop}password") + .roles("ADMIN") + .build(); + } + throw new UsernameNotFoundException("User not found"); + } +} diff --git a/sp4-oauth2-client/src/main/resources/application.yml b/sp4-oauth2-client/src/main/resources/application.yml index 11e54c5..191f04f 100644 --- a/sp4-oauth2-client/src/main/resources/application.yml +++ b/sp4-oauth2-client/src/main/resources/application.yml @@ -1,2 +1,61 @@ server: - port: 8081 + port: 8080 + + +spring: + application: + name: sp4-oauth2-demo + # OAuth2客户端配置 + security: + oauth2: + client: + registration: + login-client: + provider: spring + client-id: login-client + client-secret: openid-connect + client-authentication-method: client_secret_basic + authorization-grant-type: authorization_code + redirect-uri: http://127.0.0.1:8080/login/oauth2/code/login-client + scope: openid,profile,email,address + client-name: Spring + provider: + spring: + authorization-uri: http://localhost:9000/oauth2/authorize + token-uri: http://localhost:9000/oauth2/token + jwk-set-uri: http://localhost:9000/oauth2/jwks + + # Google登录配置 +# google: +# client-id: your-google-client-id # 从Google Cloud Console获取 +# client-secret: your-google-client-secret # 从Google Cloud Console获取 +# scope: # 请求的权限范围 +# - openid +# - profile +# - email +# redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}" # 回调地址 +# authorization-grant-type: authorization_code # 授权码模式 +# client-name: Google # 客户端显示名称 +# # GitHub登录配置 +# github: +# client-id: your-github-client-id # 从GitHub Settings > Developer settings > OAuth Apps获取 +# client-secret: your-github-client-secret +# scope: +# - read:user +# - user:email +# redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}" +# authorization-grant-type: authorization_code +# client-name: GitHub + # 提供者配置(如果使用标准OIDC提供者,可以自动发现) +# google: +# issuer-uri: https://accounts.google.com # OIDC Issuer URI,会自动发现配置 +# github: +# authorization-uri: https://github.com/login/oauth/authorize # 授权端点 +# token-uri: https://github.com/login/oauth/access_token # 令牌端点 +# user-info-uri: https://api.github.com/user # 用户信息端点 +# user-name-attribute: login # 用户名属性名 +logging: + level: + root: info + org.springframework.web: info + org.springframework.security: trace diff --git a/sp4-oauth2-resource-server/src/main/java/com/bamanker/sp4oauth2resourceserver/config/SecurityConfig.java b/sp4-oauth2-resource-server/src/main/java/com/bamanker/sp4oauth2resourceserver/config/SecurityConfig.java new file mode 100644 index 0000000..15c7c35 --- /dev/null +++ b/sp4-oauth2-resource-server/src/main/java/com/bamanker/sp4oauth2resourceserver/config/SecurityConfig.java @@ -0,0 +1,25 @@ +package com.bamanker.sp4oauth2resourceserver.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.SecurityFilterChain; + +@Configuration +public class SecurityConfig { + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .authorizeHttpRequests(authorize -> authorize + .requestMatchers("/admin/**").hasRole("ADMIN") + .anyRequest().authenticated() + ) + .formLogin(Customizer.withDefaults() + ) + .csrf(Customizer.withDefaults()) + .httpBasic(Customizer.withDefaults() + ); + return http.build(); + } +} diff --git a/sp4-oauth2-resource-server/src/main/java/com/bamanker/sp4oauth2resourceserver/controller/ApiController.java b/sp4-oauth2-resource-server/src/main/java/com/bamanker/sp4oauth2resourceserver/controller/ApiController.java new file mode 100644 index 0000000..67a1f54 --- /dev/null +++ b/sp4-oauth2-resource-server/src/main/java/com/bamanker/sp4oauth2resourceserver/controller/ApiController.java @@ -0,0 +1,40 @@ +package com.bamanker.sp4oauth2resourceserver.controller; + +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.oauth2.core.user.OAuth2User; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +/** + * API控制器 + * 演示OAuth2资源服务器保护API + */ +@RestController +@RequestMapping("/api") +public class ApiController { + /** + * 用户API + * 需要有效的OAuth2访问令牌 + */ + @GetMapping("/user/info") + public Map userInfo() { + return Map.of( + "message", "这是受保护的API" + ); + } + + /** + * 管理员API + * 需要admin权限 + */ + @GetMapping("/admin/data") + public Map adminData() { + return Map.of( + "message", "这是管理员API" + ); + } +} \ No newline at end of file diff --git a/sp4-oauth2-resource-server/src/main/java/com/bamanker/sp4oauth2resourceserver/service/CustomUserDetailsService.java b/sp4-oauth2-resource-server/src/main/java/com/bamanker/sp4oauth2resourceserver/service/CustomUserDetailsService.java new file mode 100644 index 0000000..6c3da8e --- /dev/null +++ b/sp4-oauth2-resource-server/src/main/java/com/bamanker/sp4oauth2resourceserver/service/CustomUserDetailsService.java @@ -0,0 +1,22 @@ +package com.bamanker.sp4oauth2resourceserver.service; + +import org.jspecify.annotations.NonNull; +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.stereotype.Service; + +@Service +public class CustomUserDetailsService implements UserDetailsService { + @Override + public UserDetails loadUserByUsername(@NonNull String username) throws UsernameNotFoundException { + if ("admin".equals(username)) { + return User.withUsername("admin") + .password("{noop}password") + .roles("ADMIN") + .build(); + } + throw new UsernameNotFoundException("User not found"); + } +} diff --git a/sp4-oauth2-resource-server/src/main/resources/application.yml b/sp4-oauth2-resource-server/src/main/resources/application.yml index a7afc92..bd9ff61 100644 --- a/sp4-oauth2-resource-server/src/main/resources/application.yml +++ b/sp4-oauth2-resource-server/src/main/resources/application.yml @@ -1,2 +1,9 @@ server: - port: 8080 + port: 8081 + +spring: + application: + name: sp4-oauth2-resource-server +logging: + level: + org.springframework.security: trace