diff --git a/pom.xml b/pom.xml
index 5295f86..138b5f4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,22 +32,26 @@
UTF-8
17
17
- 3.2.0
- 2.0.9
+ 3.5.3
+
+ 1.1.0.RELEASE
+ 1.1.0.RELEASE
+
+
+ com.arrokoth.framework.boot
+ arrokoth-framework-starter
+ ${arrokoth.version}
+
+
com.arrokoth.framework
basic-authorization-server
1.0.1-RELEASE
-
- org.springframework.boot
- spring-boot-starter-web
-
-
org.springframework.boot
@@ -122,8 +126,21 @@
+
+
+
+ com.arrokoth.framework.boot
+ arrokoth-framework-springboot-dependencies
+ ${arrokoth.bom.version}
+ pom
+ import
+
+
+
+
+ ${project.basedir}/target
org.springframework.boot
@@ -139,7 +156,8 @@
- build-info
+ build-info
+ repackage
@@ -150,20 +168,27 @@
maven-compiler-plugin
3.11.0
- true
+ true
17
17
- true
- true
- UTF-8
- false
+ true
+ true
+ UTF-8
+ false
org.apache.maven.plugins
maven-surefire-plugin
-
2.22.0
+
+
+ false
+
+ **/*Test.java
+ **/*Tests.java
+
+
diff --git a/src/main/java/com/arrokoth/standalone/authorization/StandaloneServerApplication.java b/src/main/java/com/arrokoth/standalone/authorization/StandaloneServerApplication.java
index 31c2553..2c743ff 100644
--- a/src/main/java/com/arrokoth/standalone/authorization/StandaloneServerApplication.java
+++ b/src/main/java/com/arrokoth/standalone/authorization/StandaloneServerApplication.java
@@ -1,12 +1,12 @@
package com.arrokoth.standalone.authorization;
-import org.mybatis.spring.annotation.MapperScan;
+import com.arrokoth.basic.annotation.EnableArrokothBasicModule;
+import com.arrokoth.framework.boot.annotation.EnableGracefulRestResponse;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.annotation.ComponentScan;
-@MapperScan("com.arrokoth.basic.mapper")
-@ComponentScan(basePackages = "com.arrokoth")
+@EnableGracefulRestResponse
+@EnableArrokothBasicModule
@SpringBootApplication
public class StandaloneServerApplication {
diff --git a/src/main/java/com/arrokoth/standalone/authorization/config/AuthorizationServerAutoConfigurer.java b/src/main/java/com/arrokoth/standalone/authorization/config/AuthorizationServerAutoConfigurer.java
index ae6dcd3..bc62348 100644
--- a/src/main/java/com/arrokoth/standalone/authorization/config/AuthorizationServerAutoConfigurer.java
+++ b/src/main/java/com/arrokoth/standalone/authorization/config/AuthorizationServerAutoConfigurer.java
@@ -12,10 +12,7 @@ import org.springframework.security.config.annotation.method.configuration.Enabl
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
-import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
-import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer;
-import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.util.matcher.MediaTypeRequestMatcher;
@@ -76,19 +73,6 @@ public class AuthorizationServerAutoConfigurer {
}
- @Bean
- public AuthorizationServerSettings authorizationServerSettings() {
- return AuthorizationServerSettings.builder()
- .authorizationEndpoint(authorizationServerProperties.getAuthorizationEndpoint()) // 授权端点路径
- .issuer(authorizationServerProperties.getIssuer()) // 授权服务器的唯一标识符(Issuer)
- .build();
- }
-
-
- @Bean
- public PasswordEncoder passwordEncoder() {
- return new BCryptPasswordEncoder(); // 仅用于演示,生产环境请使用BCryptPasswordEncoder
- }
}
\ No newline at end of file
diff --git a/src/main/java/com/arrokoth/standalone/authorization/config/OAuth2Config.java b/src/main/java/com/arrokoth/standalone/authorization/config/OAuth2Config.java
new file mode 100644
index 0000000..82c3776
--- /dev/null
+++ b/src/main/java/com/arrokoth/standalone/authorization/config/OAuth2Config.java
@@ -0,0 +1,30 @@
+package com.arrokoth.standalone.authorization.config;
+
+import com.arrokoth.basic.properties.AuthorizationServerProperties;
+import com.arrokoth.basic.properties.SecurityWebProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
+
+@Configuration
+public class OAuth2Config {
+
+
+ @Bean
+ public AuthorizationServerSettings authorizationServerSettings(AuthorizationServerProperties authorizationServerProperties,
+ SecurityWebProperties securityWebProperties) {
+ return AuthorizationServerSettings.builder()
+ .authorizationEndpoint(authorizationServerProperties.getAuthorizationEndpoint()) // 授权端点路径
+ .issuer(authorizationServerProperties.getIssuer()) // 授权服务器的唯一标识符(Issuer)
+ .build();
+ }
+
+
+ @Bean
+ public PasswordEncoder passwordEncoder() {
+ return new BCryptPasswordEncoder(); // 仅用于演示,生产环境请使用BCryptPasswordEncoder
+ }
+
+}
diff --git a/src/main/java/com/arrokoth/standalone/authorization/config/SecurityWebAutoConfigurer.java b/src/main/java/com/arrokoth/standalone/authorization/config/SecurityWebAutoConfigurer.java
index 18e52c0..e69a87c 100644
--- a/src/main/java/com/arrokoth/standalone/authorization/config/SecurityWebAutoConfigurer.java
+++ b/src/main/java/com/arrokoth/standalone/authorization/config/SecurityWebAutoConfigurer.java
@@ -1,12 +1,10 @@
package com.arrokoth.standalone.authorization.config;
-import com.arrokoth.basic.autoconfiguration.BasicAutoConfiguration;
import com.arrokoth.basic.properties.SecurityWebProperties;
import com.arrokoth.standalone.authorization.filter.JwtRequestFilter;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -27,7 +25,6 @@ import java.util.List;
@Slf4j
@Configuration
-@AutoConfigureBefore(BasicAutoConfiguration.class)
@AllArgsConstructor
@EnableConfigurationProperties(SecurityWebProperties.class)
public class SecurityWebAutoConfigurer {
@@ -55,10 +52,17 @@ public class SecurityWebAutoConfigurer {
.loginProcessingUrl(securityWebProperties.getLoginProcessingUrl())
.permitAll()
)
+
+
.logout(logout -> logout
+ .logoutUrl(SecurityWebProperties.AXIOS_LOGOUT_PROCESSING_URL)
.logoutSuccessUrl(securityWebProperties.getLogoutSuccessUrl())
+ .invalidateHttpSession(true) // 注销时销毁 session
+ .deleteCookies("JSESSIONID", "Authorization")
.permitAll()
);
+
+
return http.build();
}
@@ -72,10 +76,10 @@ public class SecurityWebAutoConfigurer {
public CorsConfigurationSource corsConfigurationSource() {
log.info("Configuring cors configuration source");
CorsConfiguration configuration = new CorsConfiguration();
+ configuration.setExposedHeaders(List.of("Authorization")); // 允许前端访问Authorization头
configuration.setAllowedOrigins(List.of("*")); // 替换为前端域名
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
- configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type", "X-Requested-With", "accept"));
- configuration.setExposedHeaders(List.of("Authorization")); // 允许前端访问Authorization头
+ configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type", "X-Requested-With", "accept", "X-XSRF-TOKEN"));
configuration.setAllowCredentials(false);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
diff --git a/src/main/java/com/arrokoth/standalone/authorization/controller/AuthorizationController.java b/src/main/java/com/arrokoth/standalone/authorization/controller/AuthorizationController.java
index d1ca468..dbb6f6a 100644
--- a/src/main/java/com/arrokoth/standalone/authorization/controller/AuthorizationController.java
+++ b/src/main/java/com/arrokoth/standalone/authorization/controller/AuthorizationController.java
@@ -2,14 +2,24 @@ package com.arrokoth.standalone.authorization.controller;
import com.arrokoth.standalone.authorization.service.OAuth2ConsentService;
import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
+import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.security.Principal;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+@Slf4j
+@Lazy
@Controller
@RequiredArgsConstructor
public class AuthorizationController {
@@ -19,6 +29,7 @@ public class AuthorizationController {
private final OAuth2ConsentService oAuth2ConsentService;
+
@GetMapping("/login")
public String home() {
return "login"; // 对应templates/login.html
@@ -33,15 +44,71 @@ public class AuthorizationController {
@RequestParam("state") String state,
@RequestParam(name = "user_code", required = false) String userCode) {
- OAuth2ConsentService.ConsentResponse viewModel = oAuth2ConsentService.getConsentDetails(principal, clientId, scope, state, userCode);
+ OAuth2ConsentService.ConsentResponse viewModel = oAuth2ConsentService.getConsentDetails(principal, clientId, scope, state, principal.getName());
+
+ model.addAttribute("clientId", clientId);
+ model.addAttribute("state", state);
+ model.addAttribute("scopes", withDescription(viewModel.scopesToApprove()));
+ model.addAttribute("previouslyApprovedScopes", withDescription(viewModel.previouslyApprovedScopes()));
+ model.addAttribute("principalName", principal.getName());
+ model.addAttribute("userCode", userCode);
+ if (StringUtils.hasText(userCode)) {
+ model.addAttribute("requestURI", "/oauth2/device_verification");
+ } else {
+ model.addAttribute("requestURI", "/oauth2/authorize");
+ }
-// model.addAttribute("clientId", viewModel.clientId());
-// model.addAttribute("state", viewModel.state());
-// model.addAttribute("scopes", viewModel.scopes());
- model.addAttribute("previouslyApprovedScopes", viewModel.previouslyApprovedScopes());
-// model.addAttribute("principalName", viewModel.principalName());
-// model.addAttribute("userCode", viewModel.userCode());
-// model.addAttribute("requestURI", viewModel.requestURI());
return "consent";
}
+
+
+ private static Set withDescription(Set scopes) {
+ Set scopeWithDescriptions = new HashSet<>();
+ for (String scope : scopes) {
+ scopeWithDescriptions.add(new ScopeWithDescription(scope));
+
+ }
+ return scopeWithDescriptions;
+ }
+
+
+ public static class ScopeWithDescription {
+ private static final String DEFAULT_DESCRIPTION = "UNKNOWN SCOPE - We cannot provide information about this permission, use caution when granting this.";
+ private static final Map scopeDescriptions = new HashMap<>();
+
+ static {
+ scopeDescriptions.put(
+ OidcScopes.PROFILE,
+ "This application will be able to read your profile information."
+ );
+ scopeDescriptions.put(
+ "message.read",
+ "This application will be able to read your message."
+ );
+ scopeDescriptions.put(
+ "message.write",
+ "This application will be able to add new messages. It will also be able to edit and delete existing messages."
+ );
+ scopeDescriptions.put(
+ "user.read",
+ "This application will be able to read your user information."
+ );
+ scopeDescriptions.put(
+ "other.scope",
+ "This is another scope example of a scope description."
+ );
+ }
+
+ public final String scope;
+ public final String description;
+
+ ScopeWithDescription(String scope) {
+ this.scope = scope;
+ this.description = scopeDescriptions.getOrDefault(scope, DEFAULT_DESCRIPTION);
+ }
+ }
+
+
+
+
}
\ No newline at end of file
diff --git a/src/main/java/com/arrokoth/standalone/authorization/store/RegisteredClientRepositoryStore.java b/src/main/java/com/arrokoth/standalone/authorization/store/RegisteredClientRepositoryStore.java
index 8887d44..c100513 100644
--- a/src/main/java/com/arrokoth/standalone/authorization/store/RegisteredClientRepositoryStore.java
+++ b/src/main/java/com/arrokoth/standalone/authorization/store/RegisteredClientRepositoryStore.java
@@ -18,12 +18,12 @@ import java.util.UUID;
@Configuration
public class RegisteredClientRepositoryStore {
+
@Bean
public RegisteredClientRepository registeredClientRepository() {
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
RegisteredClient oidcClient = RegisteredClient.withId(UUID.randomUUID().toString())
-
.clientId("messaging-client")
.clientSecret(bCryptPasswordEncoder.encode("secret"))
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
@@ -31,6 +31,7 @@ public class RegisteredClientRepositoryStore {
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.redirectUri("http://127.0.0.1:8091/login/oauth2/code/messaging-client-oidc")
+ .postLogoutRedirectUri("http://127.0.0.1:8080/logged-out")
.scope(OidcScopes.OPENID)
.scope(OidcScopes.PROFILE)
.scope("message.read")
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 3673b40..d18dcec 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -1,6 +1,32 @@
server:
port: 8080
+arrokoth:
+ authorization:
+ server:
+ consent-page: /oauth2/consent
+ authorization-endpoint: /oauth2/authorize
+ issuer: http://127.0.0.1
+ security:
+ web:
+ swagger-ui: false
+ login-page: /login
+ logout-success-url: /login?logout
+ permit-urls:
+ - /home/login
+ - /login/oauth2/**
+ - /oauth2/token
+
+ # RestApi增强配置
+ graceful-rest-response:
+ enabled: true
+ banner: true
+ print-exception-in-global-advice: true
+ origin-exception-using-detail-message: false
+ exclude-urls:
+ - "/swagger-resources"
+ - "/v3/api-docs/*"
+ - "/v2/api-docs"
spring:
@@ -27,19 +53,8 @@ spring:
max-wait: 2000ms # 获取连接最大等待时间
-arrokoth:
- authorization:
- server:
- consent-page: /oauth2/consent
- authorization-endpoint: /oauth2/authorize
- issuer: https://www.arrokoth-info.com
- security:
- web:
- swagger-ui: false
- login-page: /login
- logout-success-url: /login?logout
- permit-urls:
- - /home/login
+
+
logging: