Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
alvachien
spring-auth-server-demo
提交
c593d624
S
spring-auth-server-demo
项目概览
alvachien
/
spring-auth-server-demo
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
spring-auth-server-demo
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
c593d624
编写于
12月 10, 2022
作者:
alvachien
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Retry new way
上级
b9107f54
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
245 addition
and
145 deletion
+245
-145
auth-server-demo/src/main/java/com/poc/alvachien/authserverdemo/config/AuthorizationServerConfig.java
...hien/authserverdemo/config/AuthorizationServerConfig.java
+94
-0
auth-server-demo/src/main/java/com/poc/alvachien/authserverdemo/config/SecurityConfig.java
...m/poc/alvachien/authserverdemo/config/SecurityConfig.java
+124
-140
auth-server-demo/src/main/java/com/poc/alvachien/authserverdemo/controller/MainController.java
...c/alvachien/authserverdemo/controller/MainController.java
+9
-3
auth-server-demo/src/main/resources/templates/login.html
auth-server-demo/src/main/resources/templates/login.html
+18
-2
未找到文件。
auth-server-demo/src/main/java/com/poc/alvachien/authserverdemo/config/AuthorizationServerConfig.java
0 → 100644
浏览文件 @
c593d624
package
com.poc.alvachien.authserverdemo.config
;
import
com.nimbusds.jose.jwk.JWKSet
;
import
com.nimbusds.jose.jwk.RSAKey
;
import
com.nimbusds.jose.jwk.source.ImmutableJWKSet
;
import
com.nimbusds.jose.jwk.source.JWKSource
;
import
com.nimbusds.jose.proc.SecurityContext
;
import
java.security.KeyPair
;
import
java.security.KeyPairGenerator
;
import
java.security.interfaces.RSAPrivateKey
;
import
java.security.interfaces.RSAPublicKey
;
import
java.util.UUID
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.core.Ordered
;
import
org.springframework.core.annotation.Order
;
import
org.springframework.security.config.Customizer
;
import
org.springframework.security.config.annotation.web.builders.HttpSecurity
;
import
org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer
;
import
org.springframework.security.oauth2.jwt.JwtDecoder
;
import
org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration
;
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
;
@Configuration
(
proxyBeanMethods
=
false
)
public
class
AuthorizationServerConfig
{
@Bean
@Order
(
Ordered
.
HIGHEST_PRECEDENCE
)
public
SecurityFilterChain
authorizationServerSecurityFilterChain
(
HttpSecurity
http
)
throws
Exception
{
OAuth2AuthorizationServerConfiguration
.
applyDefaultSecurity
(
http
);
http
.
getConfigurer
(
OAuth2AuthorizationServerConfigurer
.
class
)
.
oidc
(
Customizer
.
withDefaults
());
// Enable OpenID Connect 1.0
http
.
exceptionHandling
(
exceptions
->
exceptions
.
authenticationEntryPoint
(
new
LoginUrlAuthenticationEntryPoint
(
"/login"
))
)
.
oauth2ResourceServer
(
OAuth2ResourceServerConfigurer:
:
jwt
);
return
http
.
build
();
}
// @Bean
// public OAuth2AuthorizationService authorizationService(JdbcTemplate jdbcTemplate, RegisteredClientRepository registeredClientRepository) {
// return new JdbcOAuth2AuthorizationService(jdbcTemplate, registeredClientRepository);
// }
// @Bean
// public OAuth2AuthorizationConsentService authorizationConsentService(JdbcTemplate jdbcTemplate, RegisteredClientRepository registeredClientRepository) {
// return new JdbcOAuth2AuthorizationConsentService(jdbcTemplate, registeredClientRepository);
// }
@Bean
public
JWKSource
<
SecurityContext
>
jwkSource
()
{
KeyPair
keyPair
=
generateRsaKey
();
RSAPublicKey
publicKey
=
(
RSAPublicKey
)
keyPair
.
getPublic
();
RSAPrivateKey
privateKey
=
(
RSAPrivateKey
)
keyPair
.
getPrivate
();
RSAKey
rsaKey
=
new
RSAKey
.
Builder
(
publicKey
)
.
privateKey
(
privateKey
)
.
keyID
(
UUID
.
randomUUID
().
toString
())
.
build
();
JWKSet
jwkSet
=
new
JWKSet
(
rsaKey
);
return
new
ImmutableJWKSet
<>(
jwkSet
);
}
private
static
KeyPair
generateRsaKey
()
{
KeyPair
keyPair
;
try
{
KeyPairGenerator
keyPairGenerator
=
KeyPairGenerator
.
getInstance
(
"RSA"
);
keyPairGenerator
.
initialize
(
2048
);
keyPair
=
keyPairGenerator
.
generateKeyPair
();
}
catch
(
Exception
ex
)
{
throw
new
IllegalStateException
(
ex
);
}
return
keyPair
;
}
@Bean
public
JwtDecoder
jwtDecoder
(
JWKSource
<
SecurityContext
>
jwkSource
)
{
return
OAuth2AuthorizationServerConfiguration
.
jwtDecoder
(
jwkSource
);
}
@Bean
public
AuthorizationServerSettings
authorizationServerSettings
()
{
return
AuthorizationServerSettings
.
builder
()
.
build
();
}
}
auth-server-demo/src/main/java/com/poc/alvachien/authserverdemo/config/SecurityConfig.java
浏览文件 @
c593d624
...
...
@@ -25,6 +25,7 @@ import org.springframework.security.authentication.AuthenticationEventPublisher;
import
org.springframework.security.authentication.DefaultAuthenticationEventPublisher
;
import
org.springframework.security.config.Customizer
;
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.oauth2.server.resource.OAuth2ResourceServerConfigurer
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.GrantedAuthority
;
...
...
@@ -47,8 +48,10 @@ import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import
org.springframework.security.crypto.password.PasswordEncoder
;
import
org.springframework.security.crypto.password.Pbkdf2PasswordEncoder
;
import
org.springframework.security.crypto.scrypt.SCryptPasswordEncoder
;
import
static
org
.
springframework
.
security
.
config
.
Customizer
.
withDefaults
;
@Configuration
@EnableWebSecurity
@Configuration
(
proxyBeanMethods
=
false
)
public
class
SecurityConfig
{
private
final
MyUserDetailsService
userDetailService
;
...
...
@@ -58,151 +61,132 @@ public class SecurityConfig {
this
.
userDetailService
=
userDetailsService
;
}
@Bean
@Order
(
1
)
public
SecurityFilterChain
authorizationServerSecurityFilterChain
(
HttpSecurity
http
)
throws
Exception
{
OAuth2AuthorizationServerConfiguration
.
applyDefaultSecurity
(
http
);
//http.sessionManagement().
http
.
getConfigurer
(
OAuth2AuthorizationServerConfigurer
.
class
)
.
oidc
(
Customizer
.
withDefaults
());
// Enable OpenID Connect 1.0
// http
// .authorizeRequests(authorizeRequests ->
// authorizeRequests
// .mvcMatchers("/assets/**", "/webjars/**", "/login").permitAll()
// .anyRequest().authenticated()
// )
http
// .csrf().disable()
// Redirect to the login page when not authenticated from the authorization endpoint
.
exceptionHandling
((
exceptions
)
->
exceptions
.
authenticationEntryPoint
(
new
LoginUrlAuthenticationEntryPoint
(
"/login"
))
)
// Accept access tokens for User Info and/or Client Registration
.
oauth2ResourceServer
(
OAuth2ResourceServerConfigurer:
:
jwt
);
return
http
.
build
();
}
@Bean
@Order
(
2
)
public
SecurityFilterChain
defaultSecurityFilterChain
(
HttpSecurity
http
)
throws
Exception
{
// @Bean
// @Order(1)
// public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
// OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
// //http.sessionManagement().
// http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
// .oidc(Customizer.withDefaults()); // Enable OpenID Connect 1.0
// // http
// // .authorizeRequests(authorizeRequests ->
// // authorizeRequests
// // .mvcMatchers("/assets/**", "/webjars/**", "/login").permitAll()
// // .anyRequest().authenticated()
// // )
// http
// // .csrf().disable()
// // Redirect to the login page when not authenticated from the authorization endpoint
// .exceptionHandling((exceptions) -> exceptions
// .authenticationEntryPoint(
// new LoginUrlAuthenticationEntryPoint("/login"))
// )
// // Accept access tokens for User Info and/or Client Registration
// .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
// return http.build();
// }
// @Bean
// @Order(2)
// public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
// http
// .authorizeHttpRequests((authorize) -> authorize
// .requestMatchers("/", "/static/**", "/register**", "/home", "/about").permitAll()
// .anyRequest().authenticated()
// )
// // Form login handles the redirect to the login page from the
// // authorization server filter chain
// .formLogin(
// form -> form
// .loginPage("/login")
// //.loginProcessingUrl("/login")
// .defaultSuccessUrl("/user")
// .permitAll()
// )
// .logout(
// logout -> logout
// .logoutUrl("/logout")
// .logoutSuccessUrl("/")
// .permitAll()
// )
// .rememberMe()
// .rememberMeServices(getRememberMeServices())
// .key(SECRET_KEY)
// ;
// return http.build();
// }
// private TokenBasedRememberMeServices getRememberMeServices() {
// TokenBasedRememberMeServices services = new TokenBasedRememberMeServices(SECRET_KEY, userDetailService);
// services.setCookieName("remember-cookie");
// services.setTokenValiditySeconds(100);
// return services;
// }
// @Bean
// OAuth2TokenCustomizer<JwtEncodingContext> jwtCustomizer() {
// return context -> {
// if (OidcParameterNames.ID_TOKEN.equals(context.getTokenType().getValue())) {
// UserDetails detail = userDetailService.loadUserByUsername(context.getPrincipal().getName());
// OidcUserInfo userInfo = OidcUserInfo.builder()
// .subject(detail.getUsername())
// .name(detail.getUsername())
// .givenName("First")
// .familyName("Last")
// .middleName("Middle")
// .nickname("User")
// .preferredUsername(detail.getUsername())
// .profile("https://example.com/" + detail.getUsername())
// .picture("https://example.com/" + detail.getUsername() + ".jpg")
// .website("https://example.com")
// .email(detail.getUsername() + "@example.com")
// .emailVerified(true)
// .gender("female")
// .birthdate("1970-01-01")
// .zoneinfo("Europe/Paris")
// .locale("en-US")
// .phoneNumber("+1 (604) 555-1234;ext=5678")
// .phoneNumberVerified(false)
// // .claim("address", Collections.singletonMap("formatted", "Champ de Mars\n5 Av. Anatole France\n75007 Paris\nFrance"))
// .updatedAt("1970-01-01T00:00:00Z")
// .build();
// context.getClaims().claims(claims ->
// claims.putAll(userInfo.getClaims()));
// }
// if (context.getTokenType() == OAuth2TokenType.ACCESS_TOKEN) {
// Authentication principal = context.getPrincipal();
// Set<String> authorities = principal.getAuthorities().stream()
// .map(GrantedAuthority::getAuthority)
// .collect(Collectors.toSet());
// context.getClaims().claim("roles", authorities);
// }
// };
// }
@Bean
SecurityFilterChain
defaultSecurityFilterChain
(
HttpSecurity
http
)
throws
Exception
{
http
.
authorizeHttpRequests
((
authorize
)
->
authorize
.
requestMatchers
(
"/"
,
"/static/**"
,
"/register**"
,
"/home"
,
"/about"
).
permitAll
()
.
anyRequest
().
authenticated
()
)
// Form login handles the redirect to the login page from the
// authorization server filter chain
// .authorizeHttpRequests(authorize ->
// authorize.anyRequest().authenticated()
// )
//.formLogin(withDefaults());
.
formLogin
(
form
->
form
.
loginPage
(
"/login"
)
//.loginProcessingUrl("/login")
.
defaultSuccessUrl
(
"/user"
)
.
permitAll
()
)
.
logout
(
logout
->
logout
.
logoutUrl
(
"/logout"
)
.
logoutSuccessUrl
(
"/"
)
.
permitAll
()
form
->
form
.
loginPage
(
"/login"
).
loginProcessingUrl
(
"/login"
).
successForwardUrl
(
"/"
)
)
.
rememberMe
()
.
rememberMeServices
(
getRememberMeServices
()
)
.
key
(
SECRET_KEY
)
;
.
authorizeHttpRequests
(
requests
->
requests
.
requestMatchers
(
"/"
,
"/home"
,
"/login"
,
"/static/**"
).
permitAll
(
)
.
anyRequest
().
authenticated
(
)
)
;
return
http
.
build
();
}
private
TokenBasedRememberMeServices
getRememberMeServices
()
{
TokenBasedRememberMeServices
services
=
new
TokenBasedRememberMeServices
(
SECRET_KEY
,
userDetailService
);
services
.
setCookieName
(
"remember-cookie"
);
services
.
setTokenValiditySeconds
(
100
);
return
services
;
}
@Bean
OAuth2TokenCustomizer
<
JwtEncodingContext
>
jwtCustomizer
()
{
return
context
->
{
if
(
OidcParameterNames
.
ID_TOKEN
.
equals
(
context
.
getTokenType
().
getValue
()))
{
UserDetails
detail
=
userDetailService
.
loadUserByUsername
(
context
.
getPrincipal
().
getName
());
OidcUserInfo
userInfo
=
OidcUserInfo
.
builder
()
.
subject
(
detail
.
getUsername
())
.
name
(
detail
.
getUsername
())
.
givenName
(
"First"
)
.
familyName
(
"Last"
)
.
middleName
(
"Middle"
)
.
nickname
(
"User"
)
.
preferredUsername
(
detail
.
getUsername
())
.
profile
(
"https://example.com/"
+
detail
.
getUsername
())
.
picture
(
"https://example.com/"
+
detail
.
getUsername
()
+
".jpg"
)
.
website
(
"https://example.com"
)
.
email
(
detail
.
getUsername
()
+
"@example.com"
)
.
emailVerified
(
true
)
.
gender
(
"female"
)
.
birthdate
(
"1970-01-01"
)
.
zoneinfo
(
"Europe/Paris"
)
.
locale
(
"en-US"
)
.
phoneNumber
(
"+1 (604) 555-1234;ext=5678"
)
.
phoneNumberVerified
(
false
)
// .claim("address", Collections.singletonMap("formatted", "Champ de Mars\n5 Av. Anatole France\n75007 Paris\nFrance"))
.
updatedAt
(
"1970-01-01T00:00:00Z"
)
.
build
();
context
.
getClaims
().
claims
(
claims
->
claims
.
putAll
(
userInfo
.
getClaims
()));
}
if
(
context
.
getTokenType
()
==
OAuth2TokenType
.
ACCESS_TOKEN
)
{
Authentication
principal
=
context
.
getPrincipal
();
Set
<
String
>
authorities
=
principal
.
getAuthorities
().
stream
()
.
map
(
GrantedAuthority:
:
getAuthority
)
.
collect
(
Collectors
.
toSet
());
context
.
getClaims
().
claim
(
"roles"
,
authorities
);
}
};
}
@Bean
public
JWKSource
<
SecurityContext
>
jwkSource
()
{
KeyPair
keyPair
=
generateRsaKey
();
RSAPublicKey
publicKey
=
(
RSAPublicKey
)
keyPair
.
getPublic
();
RSAPrivateKey
privateKey
=
(
RSAPrivateKey
)
keyPair
.
getPrivate
();
RSAKey
rsaKey
=
new
RSAKey
.
Builder
(
publicKey
)
.
privateKey
(
privateKey
)
.
keyID
(
UUID
.
randomUUID
().
toString
())
.
build
();
JWKSet
jwkSet
=
new
JWKSet
(
rsaKey
);
return
new
ImmutableJWKSet
<>(
jwkSet
);
}
private
static
KeyPair
generateRsaKey
()
{
KeyPair
keyPair
;
try
{
KeyPairGenerator
keyPairGenerator
=
KeyPairGenerator
.
getInstance
(
"RSA"
);
keyPairGenerator
.
initialize
(
2048
);
keyPair
=
keyPairGenerator
.
generateKeyPair
();
}
catch
(
Exception
ex
)
{
throw
new
IllegalStateException
(
ex
);
}
return
keyPair
;
}
@Bean
public
JwtDecoder
jwtDecoder
(
JWKSource
<
SecurityContext
>
jwkSource
)
{
return
OAuth2AuthorizationServerConfiguration
.
jwtDecoder
(
jwkSource
);
}
@Bean
public
AuthorizationServerSettings
authorizationServerSettings
()
{
return
AuthorizationServerSettings
.
builder
()
.
build
();
}
@Bean
public
PasswordEncoder
passwordEncoder
()
{
String
idForEncode
=
"bcrypt"
;
...
...
auth-server-demo/src/main/java/com/poc/alvachien/authserverdemo/controller/MainController.java
浏览文件 @
c593d624
...
...
@@ -42,12 +42,18 @@ public class MainController {
@GetMapping
(
"/login"
)
public
String
loginForm
(
Model
model
)
{
log
.
info
(
"Requiring /login"
);
LoginDto
ld
=
new
LoginDto
();
model
.
addAttribute
(
"login"
,
ld
);
return
"login"
;
}
// @GetMapping("/login")
// public String loginForm(Model model) {
// log.info("Requiring /login");
// LoginDto ld = new LoginDto();
// model.addAttribute("login", ld);
// return "login";
// }
// @PostMapping("/login")
// public String login(@Valid @ModelAttribute("login") LoginDto loginData,
// BindingResult result, Model model) {
...
...
auth-server-demo/src/main/resources/templates/login.html
浏览文件 @
c593d624
...
...
@@ -17,7 +17,23 @@
</div>
<main
class=
"form-signin w-100 m-auto"
>
<form
method=
"post"
role=
"form"
th:action=
"@{/login}"
th:object=
"${login}"
>
<form
method=
"post"
th:action=
"@{/login}"
>
<h1
class=
"h3 mb-3 fw-normal"
>
Please sign in
</h1>
<div
class=
"form-group mb-3"
>
<label
for=
"username"
class=
"sr-only"
>
Email
</label>
<input
type=
"text"
id=
"username"
name=
"username"
class=
"form-control"
placeholder=
"Username"
required=
""
autofocus=
""
spellcheck=
"false"
data-ms-editor=
"true"
>
</div>
<div
class=
"form-group mb-3"
>
<label
for=
"password"
class=
"sr-only"
>
Password
</label>
<input
type=
"password"
id=
"password"
name=
"password"
class=
"form-control"
placeholder=
"Password"
required=
""
>
</div>
<button
class=
"w-100 btn btn-lg btn-primary"
type=
"submit"
>
Sign in
</button>
</form>
<!-- <form method="post" role="form" th:action="@{/login}" th:object="${login}">
<img class="mb-4" th:src="@{/static/img/logo.svg}" alt="" width="72" height="57">
<h1 class="h3 mb-3 fw-normal">Please sign in</h1>
...
...
@@ -42,7 +58,7 @@
<input type="checkbox" value="remember-me"> Remember me </label>
</div>
<button class="w-100 btn btn-lg btn-primary" type="submit">Sign in</button>
</form>
</form>
-->
</main>
<div
th:replace=
"~{fragments/footer :: footer}"
>
©
2022 - 2023
</div>
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录