第二次

This commit is contained in:
bamanker
2026-01-15 17:31:18 +08:00
parent 5be0233b88
commit d84e26ed49
10 changed files with 322 additions and 2 deletions

View File

@@ -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

View File

@@ -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();
}
}

View File

@@ -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<String, Object> 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;
}
}

View File

@@ -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);
}
}

View File

@@ -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");
}
}

View File

@@ -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

View File

@@ -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();
}
}

View File

@@ -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<String, Object> userInfo() {
return Map.of(
"message", "这是受保护的API"
);
}
/**
* 管理员API
* 需要admin权限
*/
@GetMapping("/admin/data")
public Map<String, Object> adminData() {
return Map.of(
"message", "这是管理员API"
);
}
}

View File

@@ -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");
}
}

View File

@@ -1,2 +1,9 @@
server:
port: 8080
port: 8081
spring:
application:
name: sp4-oauth2-resource-server
logging:
level:
org.springframework.security: trace