Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yd-cloud-core
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xingmin
yd-cloud-core
Commits
345cdf96
Commit
345cdf96
authored
Jul 29, 2025
by
zhangxingmin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
配置
parent
ffa894fc
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
499 additions
and
217 deletions
+499
-217
yd-auth-core/pom.xml
+27
-8
yd-auth-core/src/main/java/com/yd/auth/core/AuthApplication.java
+3
-3
yd-auth-core/src/main/java/com/yd/auth/core/config/SecurityConfig.java
+28
-22
yd-auth-core/src/main/java/com/yd/auth/core/controller/AuthController.java
+23
-25
yd-auth-core/src/main/java/com/yd/auth/core/dto/LoginRequest.java
+23
-0
yd-auth-core/src/main/java/com/yd/auth/core/dto/LoginResponse.java
+32
-0
yd-auth-core/src/main/java/com/yd/auth/core/exception/GlobalExceptionHandler.java
+25
-0
yd-auth-core/src/main/java/com/yd/auth/core/model/AuthUser.java
+17
-0
yd-auth-core/src/main/java/com/yd/auth/core/security/JwtAuthenticationEntryPoint.java
+5
-14
yd-auth-core/src/main/java/com/yd/auth/core/security/JwtAuthenticationFilter.java
+21
-39
yd-auth-core/src/main/java/com/yd/auth/core/security/JwtTokenProvider.java
+113
-0
yd-auth-core/src/main/java/com/yd/auth/core/service/AuthService.java
+5
-24
yd-auth-core/src/main/java/com/yd/auth/core/service/AuthUserDetailsService.java
+43
-0
yd-auth-core/src/main/java/com/yd/auth/core/service/impl/AuthServiceImpl.java
+35
-56
yd-auth-core/src/main/resources/banner.txt
+11
-0
yd-auth-core/src/main/resources/bootstrap.yml
+8
-2
yd-auth-core/src/main/resources/spy.properties
+29
-0
yd-common/pom.xml
+0
-1
yd-framework/src/main/java/com/yd/framework/handler/GlobalExceptionHandler.java
+19
-0
yd-gateway/src/main/java/com/yd/gateway/config/GatewaySecurityConfig.java
+32
-23
No files found.
yd-auth-core/pom.xml
View file @
345cdf96
...
...
@@ -19,12 +19,6 @@
<groupId>
com.alibaba.cloud
</groupId>
<artifactId>
spring-cloud-starter-alibaba-nacos-discovery
</artifactId>
</dependency>
<!-- SpringCloud Openfeign -->
<dependency>
<groupId>
org.springframework.cloud
</groupId>
<artifactId>
spring-cloud-starter-openfeign
</artifactId>
</dependency>
<!-- Spring Boot Starter -->
<dependency>
<groupId>
org.springframework.boot
</groupId>
...
...
@@ -75,9 +69,34 @@
<groupId>
io.projectreactor
</groupId>
<artifactId>
reactor-core
</artifactId>
</dependency>
<!--对于bootstrap.properties/bootstrap.yaml配置文件(我们合起来成为Bootstrap配置文件)的支持,需要导入如下的依赖 -->
<dependency>
<groupId>
org.springframework.cloud
</groupId>
<artifactId>
spring-cloud-starter-bootstrap
</artifactId>
</dependency>
<!-- 阿里数据库连接池 -->
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
druid-spring-boot-starter
</artifactId>
</dependency>
<dependency>
<groupId>
mysql
</groupId>
<artifactId>
mysql-connector-java
</artifactId>
</dependency>
<dependency>
<groupId>
p6spy
</groupId>
<artifactId>
p6spy
</artifactId>
</dependency>
<!-- 用户API模块 -->
<dependency>
<groupId>
org.projectlombok
</groupId>
<artifactId>
lombok
</artifactId>
<groupId>
com.yd
</groupId>
<artifactId>
yd-user-api
</artifactId>
<version>
${project.version}
</version>
</dependency>
</dependencies>
...
...
yd-auth-core/src/main/java/com/yd/auth/core/AuthApplication.java
View file @
345cdf96
...
...
@@ -6,14 +6,14 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import
org.springframework.boot.builder.SpringApplicationBuilder
;
import
org.springframework.cloud.openfeign.EnableFeignClients
;
@SpringBootApplication
@SpringBootApplication
(
scanBasePackages
=
"com.yd"
)
@MapperScan
(
"com.yd.**.mapper"
)
@EnableFeignClients
(
basePackages
=
"com.yd
.auth.core.**
"
)
@EnableFeignClients
(
basePackages
=
"com.yd"
)
public
class
AuthApplication
{
public
static
void
main
(
String
[]
args
)
{
new
SpringApplicationBuilder
(
AuthApplication
.
class
)
.
properties
(
"spring.config.name:bootstrap"
,
"config/bootstrap.yml"
)
//
.properties("spring.config.name:bootstrap", "config/bootstrap.yml")
.
properties
(
"spring.application.name="
+
ServerNameConstants
.
ydAuthCore
)
.
build
().
run
(
args
);
System
.
out
.
println
(
"(♥◠‿◠)ノ゙ yd-auth-core认证服务启动成功 ლ(´ڡ`ლ)゙ "
);
...
...
yd-auth-core/src/main/java/com/yd/auth/core/config/SecurityConfig.java
View file @
345cdf96
...
...
@@ -2,7 +2,7 @@ package com.yd.auth.core.config;
import
com.yd.auth.core.security.JwtAuthenticationEntryPoint
;
import
com.yd.auth.core.security.JwtAuthenticationFilter
;
import
com.yd.auth.core.se
curity.JwtAuthenticationProvider
;
import
com.yd.auth.core.se
rvice.AuthUserDetailsService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
...
...
@@ -20,46 +20,52 @@ import org.springframework.security.web.authentication.UsernamePasswordAuthentic
@EnableWebSecurity
public
class
SecurityConfig
extends
WebSecurityConfigurerAdapter
{
@Autowired
private
JwtAuthenticationEntryPoint
unauthorizedHandler
;
@Autowired
private
JwtAuthenticationFilter
jwtAuthenticationFilter
;
private
final
AuthUserDetailsService
userDetailsService
;
private
final
JwtAuthenticationEntryPoint
authenticationEntryPoint
;
private
final
JwtAuthenticationFilter
authenticationFilter
;
@Autowired
private
JwtAuthenticationProvider
jwtAuthenticationProvider
;
public
SecurityConfig
(
AuthUserDetailsService
userDetailsService
,
JwtAuthenticationEntryPoint
authenticationEntryPoint
,
JwtAuthenticationFilter
authenticationFilter
)
{
this
.
userDetailsService
=
userDetailsService
;
this
.
authenticationEntryPoint
=
authenticationEntryPoint
;
this
.
authenticationFilter
=
authenticationFilter
;
}
@
Override
p
rotected
void
configure
(
AuthenticationManagerBuilder
auth
)
throws
Exception
{
auth
.
authenticationProvider
(
jwtAuthenticationProvider
);
@
Bean
p
ublic
PasswordEncoder
passwordEncoder
()
{
return
new
BCryptPasswordEncoder
(
);
}
@Override
@Bean
@Override
public
AuthenticationManager
authenticationManagerBean
()
throws
Exception
{
return
super
.
authenticationManagerBean
();
}
@
Bean
p
ublic
PasswordEncoder
passwordEncoder
()
{
return
new
BCryptPasswordEncoder
(
);
@
Override
p
rotected
void
configure
(
AuthenticationManagerBuilder
auth
)
throws
Exception
{
auth
.
userDetailsService
(
userDetailsService
).
passwordEncoder
(
passwordEncoder
()
);
}
@Override
protected
void
configure
(
HttpSecurity
http
)
throws
Exception
{
http
.
csrf
().
disable
()
.
exceptionHandling
().
authenticationEntryPoint
(
unauthorizedHandler
)
.
exceptionHandling
().
authenticationEntryPoint
(
authenticationEntryPoint
)
.
and
()
.
sessionManagement
().
sessionCreationPolicy
(
SessionCreationPolicy
.
STATELESS
)
.
and
()
.
authorizeRequests
()
.
antMatchers
(
"/api/auth/**"
).
permitAll
()
.
antMatchers
(
"/v2/api-docs"
,
"/swagger-resources/configuration/ui"
,
"/swagger-resources"
,
"/swagger-resources/configuration/security"
,
"/swagger-ui.html"
,
"/webjars/**"
).
permitAll
()
.
anyRequest
().
authenticated
();
http
.
addFilterBefore
(
jwtAuthenticationFilter
,
UsernamePasswordAuthenticationFilter
.
class
);
.
antMatchers
(
"/auth/login"
,
"/auth/register"
,
"/swagger-ui/**"
,
"/v3/api-docs/**"
).
permitAll
()
.
anyRequest
().
authenticated
()
.
and
()
.
addFilterBefore
(
authenticationFilter
,
UsernamePasswordAuthenticationFilter
.
class
);
}
}
yd-auth-core/src/main/java/com/yd/auth/core/controller/AuthController.java
View file @
345cdf96
package
com
.
yd
.
auth
.
core
.
controller
;
import
com.yd.common.result.Result
;
import
com.yd.auth.core.dto.LoginRequest
;
import
com.yd.auth.core.dto.LoginResponse
;
import
com.yd.auth.core.service.AuthService
;
import
com.yd.
user.service.entity.User
;
import
com.yd.
common.result.Result
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.*
;
import
org.springframework.web.bind.annotation.PostMapping
;
import
org.springframework.web.bind.annotation.RequestBody
;
import
org.springframework.web.bind.annotation.RequestMapping
;
import
org.springframework.web.bind.annotation.RestController
;
import
java
.util.Map
;
import
java
x.validation.Valid
;
@RestController
@RequestMapping
(
"/a
pi/a
uth"
)
@RequestMapping
(
"/auth"
)
public
class
AuthController
{
@Autowired
private
AuthService
authService
;
@PostMapping
(
"/login"
)
public
Result
<?>
login
(
@RequestBody
Map
<
String
,
String
>
loginRequest
)
{
String
username
=
loginRequest
.
get
(
"username"
);
String
password
=
loginRequest
.
get
(
"password"
);
private
final
AuthService
authService
;
Map
<
String
,
String
>
tokens
=
authService
.
login
(
username
,
password
);
return
Result
.
success
(
tokens
);
@Autowired
public
AuthController
(
AuthService
authService
)
{
this
.
authService
=
authService
;
}
@PostMapping
(
"/refresh"
)
public
Result
<?>
refreshToken
(
@RequestBody
Map
<
String
,
String
>
refreshRequest
)
{
String
refreshToken
=
refreshRequest
.
get
(
"refreshToken"
);
Map
<
String
,
String
>
tokens
=
authService
.
refreshToken
(
refreshToken
);
return
Result
.
success
(
tokens
);
@PostMapping
(
"/login"
)
public
Result
<
LoginResponse
>
login
(
@Valid
@RequestBody
LoginRequest
loginRequest
)
{
LoginResponse
response
=
authService
.
login
(
loginRequest
);
return
Result
.
success
(
response
);
}
@PostMapping
(
"/register"
)
public
Result
<?>
register
(
@RequestBody
User
user
)
{
User
registeredUser
=
authService
.
register
(
user
);
return
Result
.
success
(
registeredUser
);
}
// @PostMapping("/logout")
// public Result<Void> logout() {
// // 实际实现需要前端传递token
// // 这里简化处理
// return R.success("登出成功");
// }
}
yd-auth-core/src/main/java/com/yd/auth/core/dto/LoginRequest.java
0 → 100644
View file @
345cdf96
package
com
.
yd
.
auth
.
core
.
dto
;
public
class
LoginRequest
{
private
String
username
;
private
String
password
;
// Getters and Setters
public
String
getUsername
()
{
return
username
;
}
public
void
setUsername
(
String
username
)
{
this
.
username
=
username
;
}
public
String
getPassword
()
{
return
password
;
}
public
void
setPassword
(
String
password
)
{
this
.
password
=
password
;
}
}
yd-auth-core/src/main/java/com/yd/auth/core/dto/LoginResponse.java
0 → 100644
View file @
345cdf96
package
com
.
yd
.
auth
.
core
.
dto
;
public
class
LoginResponse
{
private
String
token
;
private
String
tokenType
=
"Bearer"
;
private
long
expiresIn
;
// Getters and Setters
public
String
getToken
()
{
return
token
;
}
public
void
setToken
(
String
token
)
{
this
.
token
=
token
;
}
public
String
getTokenType
()
{
return
tokenType
;
}
public
void
setTokenType
(
String
tokenType
)
{
this
.
tokenType
=
tokenType
;
}
public
long
getExpiresIn
()
{
return
expiresIn
;
}
public
void
setExpiresIn
(
long
expiresIn
)
{
this
.
expiresIn
=
expiresIn
;
}
}
yd-auth-core/src/main/java/com/yd/auth/core/exception/GlobalExceptionHandler.java
0 → 100644
View file @
345cdf96
package
com
.
yd
.
auth
.
core
.
exception
;
import
com.yd.auth.core.security.JwtTokenProvider
;
import
com.yd.common.result.Result
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.security.authentication.BadCredentialsException
;
import
org.springframework.web.bind.annotation.ExceptionHandler
;
import
org.springframework.web.bind.annotation.ResponseStatus
;
import
org.springframework.web.bind.annotation.RestControllerAdvice
;
@RestControllerAdvice
public
class
GlobalExceptionHandler
{
@ExceptionHandler
(
BadCredentialsException
.
class
)
@ResponseStatus
(
HttpStatus
.
UNAUTHORIZED
)
public
Result
<?>
handleBadCredentialsException
(
BadCredentialsException
e
)
{
return
Result
.
fail
(
401
,
"用户名或密码错误"
);
}
@ExceptionHandler
(
JwtTokenProvider
.
JwtAuthenticationException
.
class
)
@ResponseStatus
(
HttpStatus
.
UNAUTHORIZED
)
public
Result
<?>
handleJwtAuthenticationException
(
JwtTokenProvider
.
JwtAuthenticationException
e
)
{
return
Result
.
fail
(
401
,
e
.
getMessage
());
}
}
yd-auth-core/src/main/java/com/yd/auth/core/model/AuthUser.java
0 → 100644
View file @
345cdf96
package
com
.
yd
.
auth
.
core
.
model
;
import
lombok.Getter
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.security.core.userdetails.User
;
import
java.util.Collection
;
@Getter
public
class
AuthUser
extends
User
{
private
final
Long
id
;
public
AuthUser
(
Long
id
,
String
username
,
String
password
,
Collection
<?
extends
GrantedAuthority
>
authorities
)
{
super
(
username
,
password
,
authorities
);
this
.
id
=
id
;
}
}
yd-auth-core/src/main/java/com/yd/auth/core/security/JwtAuthenticationEntryPoint.java
View file @
345cdf96
package
com
.
yd
.
auth
.
core
.
security
;
import
com.alibaba.fastjson.JSON
;
import
com.yd.common.result.Result
;
import
org.springframework.security.core.AuthenticationException
;
import
org.springframework.security.web.AuthenticationEntryPoint
;
import
org.springframework.stereotype.Component
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
...
...
@@ -14,16 +12,9 @@ import java.io.IOException;
public
class
JwtAuthenticationEntryPoint
implements
AuthenticationEntryPoint
{
@Override
public
void
commence
(
HttpServletRequest
request
,
HttpServletResponse
response
,
AuthenticationException
authException
)
throws
IOException
,
ServletException
{
// 设置响应状态码为401
response
.
setStatus
(
HttpServletResponse
.
SC_UNAUTHORIZED
);
// 设置响应内容类型
response
.
setContentType
(
"application/json;charset=UTF-8"
);
// 返回统一的错误响应
Result
<?>
result
=
Result
.
fail
(
401
,
"未经授权: "
+
authException
.
getMessage
());
response
.
getWriter
().
write
(
JSON
.
toJSONString
(
result
));
public
void
commence
(
HttpServletRequest
request
,
HttpServletResponse
response
,
AuthenticationException
authException
)
throws
IOException
{
response
.
sendError
(
HttpServletResponse
.
SC_UNAUTHORIZED
,
"未经授权的访问"
);
}
}
yd-auth-core/src/main/java/com/yd/auth/core/security/JwtAuthenticationFilter.java
View file @
345cdf96
package
com
.
yd
.
auth
.
core
.
security
;
import
com.yd.auth.core.utils.JwtUtils
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.security.core.userdetails.UserDetailsService
;
import
org.springframework.security.web.authentication.WebAuthenticationDetailsSource
;
import
org.springframework.stereotype.Component
;
import
org.springframework.util.StringUtils
;
import
org.springframework.web.filter.OncePerRequestFilter
;
import
javax.servlet.FilterChain
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.HttpServletRequest
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.IOException
;
@Slf4j
@Component
public
class
JwtAuthenticationFilter
extends
OncePerRequestFilter
{
@Autowired
private
JwtUtils
jwtUtils
;
private
final
JwtTokenProvider
tokenProvider
;
private
final
UserDetailsService
userDetailsService
;
@Autowired
private
UserDetailsService
userDetailsService
;
public
JwtAuthenticationFilter
(
JwtTokenProvider
tokenProvider
,
UserDetailsService
userDetailsService
)
{
this
.
tokenProvider
=
tokenProvider
;
this
.
userDetailsService
=
userDetailsService
;
}
@Override
protected
void
doFilterInternal
(
HttpServletRequest
request
,
HttpServletResponse
response
,
FilterChain
filterChain
)
throws
ServletException
,
IOException
{
try
{
// 从请求头中获取JWT令牌
String
jwt
=
parseJwt
(
request
);
if
(
jwt
!=
null
&&
jwtUtils
.
validateToken
(
jwt
))
{
// 从JWT中获取用户名
String
username
=
jwtUtils
.
getUsernameFromToken
(
jwt
);
// 加载用户详情
protected
void
doFilterInternal
(
HttpServletRequest
request
,
HttpServletResponse
response
,
FilterChain
filterChain
)
throws
ServletException
,
IOException
{
String
token
=
resolveToken
(
request
);
if
(
token
!=
null
&&
tokenProvider
.
validateToken
(
token
))
{
String
username
=
tokenProvider
.
getUsernameFromToken
(
token
);
// 从数据库加载用户信息
UserDetails
userDetails
=
userDetailsService
.
loadUserByUsername
(
username
);
// 创建认证令牌
UsernamePasswordAuthenticationToken
authentication
=
new
UsernamePasswordAuthenticationToken
(
userDetails
,
null
,
userDetails
.
getAuthorities
()
);
authentication
.
setDetails
(
new
WebAuthenticationDetailsSource
().
buildDetails
(
request
));
// 将认证信息设置到SecurityContext中
new
UsernamePasswordAuthenticationToken
(
userDetails
,
null
,
userDetails
.
getAuthorities
());
SecurityContextHolder
.
getContext
().
setAuthentication
(
authentication
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
"无法设置用户认证: {}"
,
e
.
getMessage
());
}
filterChain
.
doFilter
(
request
,
response
);
}
private
String
parseJwt
(
HttpServletRequest
request
)
{
String
headerAuth
=
request
.
getHeader
(
"Authorization"
);
if
(
headerAuth
!=
null
&&
headerAuth
.
startsWith
(
"Bearer "
))
{
return
headerAuth
.
substring
(
7
);
private
String
resolveToken
(
HttpServletRequest
request
)
{
String
bearerToken
=
request
.
getHeader
(
"Authorization"
);
if
(
StringUtils
.
hasText
(
bearerToken
)
&&
bearerToken
.
startsWith
(
"Bearer "
))
{
return
bearerToken
.
substring
(
7
);
}
return
null
;
}
}
yd-auth-core/src/main/java/com/yd/auth/core/security/JwtTokenProvider.java
0 → 100644
View file @
345cdf96
package
com
.
yd
.
auth
.
core
.
security
;
import
io.jsonwebtoken.*
;
import
io.jsonwebtoken.security.Keys
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.GrantedAuthority
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.stereotype.Component
;
import
javax.crypto.SecretKey
;
import
java.util.Collection
;
import
java.util.Date
;
import
java.util.stream.Collectors
;
@Component
public
class
JwtTokenProvider
{
@Value
(
"${jwt.secret}"
)
private
String
jwtSecret
;
@Value
(
"${jwt.expiration}"
)
private
int
jwtExpiration
;
public
String
generateToken
(
Authentication
authentication
)
{
UserDetails
userDetails
=
(
UserDetails
)
authentication
.
getPrincipal
();
return
Jwts
.
builder
()
.
setSubject
(
userDetails
.
getUsername
())
.
claim
(
"roles"
,
getRoles
(
userDetails
.
getAuthorities
()))
.
setIssuedAt
(
new
Date
())
.
setExpiration
(
new
Date
(
System
.
currentTimeMillis
()
+
jwtExpiration
*
1000L
))
.
signWith
(
getSigningKey
(),
SignatureAlgorithm
.
HS512
)
.
compact
();
}
private
Collection
<
String
>
getRoles
(
Collection
<?
extends
GrantedAuthority
>
authorities
)
{
return
authorities
.
stream
()
.
map
(
GrantedAuthority:
:
getAuthority
)
.
collect
(
Collectors
.
toList
());
}
public
String
getUsernameFromToken
(
String
token
)
{
return
Jwts
.
parserBuilder
()
.
setSigningKey
(
getSigningKey
())
.
build
()
.
parseClaimsJws
(
token
)
.
getBody
()
.
getSubject
();
}
public
Authentication
getAuthentication
(
String
token
)
{
if
(
validateToken
(
token
))
{
String
username
=
getUsernameFromToken
(
token
);
// 这里应该从数据库加载用户信息,但为了性能通常只加载基本信息
// 实际项目中可以在这里加载用户权限
return
new
UsernamePasswordAuthenticationToken
(
username
,
null
,
// 从token中提取权限
getAuthoritiesFromToken
(
token
)
);
}
return
null
;
}
private
Collection
<?
extends
GrantedAuthority
>
getAuthoritiesFromToken
(
String
token
)
{
Claims
claims
=
Jwts
.
parserBuilder
()
.
setSigningKey
(
getSigningKey
())
.
build
()
.
parseClaimsJws
(
token
)
.
getBody
();
@SuppressWarnings
(
"unchecked"
)
Collection
<
String
>
roles
=
(
Collection
<
String
>)
claims
.
get
(
"roles"
);
return
roles
.
stream
()
.
map
(
role
->
(
GrantedAuthority
)
()
->
role
)
.
collect
(
Collectors
.
toList
());
}
public
boolean
validateToken
(
String
token
)
{
try
{
Jwts
.
parserBuilder
().
setSigningKey
(
getSigningKey
()).
build
().
parseClaimsJws
(
token
);
return
true
;
}
catch
(
SecurityException
|
MalformedJwtException
e
)
{
throw
new
JwtAuthenticationException
(
"无效的JWT签名"
);
}
catch
(
ExpiredJwtException
e
)
{
throw
new
JwtAuthenticationException
(
"JWT令牌已过期"
);
}
catch
(
UnsupportedJwtException
e
)
{
throw
new
JwtAuthenticationException
(
"不支持的JWT令牌"
);
}
catch
(
IllegalArgumentException
e
)
{
throw
new
JwtAuthenticationException
(
"JWT令牌无效"
);
}
catch
(
Exception
e
)
{
throw
new
JwtAuthenticationException
(
"无效的JWT令牌"
);
}
}
private
SecretKey
getSigningKey
()
{
return
Keys
.
hmacShaKeyFor
(
jwtSecret
.
getBytes
());
}
public
int
getJwtExpiration
()
{
return
jwtExpiration
;
}
public
static
class
JwtAuthenticationException
extends
RuntimeException
{
public
JwtAuthenticationException
(
String
message
)
{
super
(
message
);
}
}
}
yd-auth-core/src/main/java/com/yd/auth/core/service/AuthService.java
View file @
345cdf96
package
com
.
yd
.
auth
.
core
.
service
;
import
com.yd.auth.core.
security.JwtAuthenticationToken
;
import
com.yd.
user.service.entity.User
;
import
com.yd.auth.core.
dto.LoginRequest
;
import
com.yd.
auth.core.dto.LoginResponse
;
import
org.springframework.security.core.Authentication
;
import
java.util.Map
;
public
interface
AuthService
{
/**
* 用户登录
*/
Map
<
String
,
String
>
login
(
String
username
,
String
password
);
/**
* 刷新令牌
*/
Map
<
String
,
String
>
refreshToken
(
String
refreshToken
);
/**
* 验证令牌
*/
Authentication
validateToken
(
String
token
);
/**
* 注册新用户
*/
User
register
(
User
user
);
LoginResponse
login
(
LoginRequest
loginRequest
);
void
logout
(
String
token
);
Authentication
getAuthentication
(
String
token
);
}
yd-auth-core/src/main/java/com/yd/auth/core/service/AuthUserDetailsService.java
0 → 100644
View file @
345cdf96
package
com
.
yd
.
auth
.
core
.
service
;
import
com.yd.auth.core.model.AuthUser
;
import
com.yd.user.api.dto.UserDTO
;
import
com.yd.user.api.feign.UserFeignClient
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.security.core.authority.SimpleGrantedAuthority
;
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
;
import
java.util.stream.Collectors
;
@Service
public
class
AuthUserDetailsService
implements
UserDetailsService
{
private
final
UserFeignClient
userFeignClient
;
@Autowired
public
AuthUserDetailsService
(
UserFeignClient
userFeignClient
)
{
this
.
userFeignClient
=
userFeignClient
;
}
@Override
public
UserDetails
loadUserByUsername
(
String
username
)
throws
UsernameNotFoundException
{
// 通过Feign调用yd-user服务获取用户信息
UserDTO
user
=
userFeignClient
.
findByUsername
(
username
);
if
(
user
==
null
)
{
throw
new
UsernameNotFoundException
(
"用户不存在:"
+
username
);
}
// 转换为Spring Security用户对象
return
new
AuthUser
(
user
.
getId
(),
user
.
getUsername
(),
user
.
getPassword
(),
user
.
getRoles
().
stream
()
.
map
(
role
->
new
SimpleGrantedAuthority
(
role
))
// 修正类名
.
collect
(
Collectors
.
toList
())
);
}
}
yd-auth-core/src/main/java/com/yd/auth/core/service/impl/AuthServiceImpl.java
View file @
345cdf96
package
com
.
yd
.
auth
.
core
.
service
.
impl
;
import
com.yd.auth.core.security.JwtAuthenticationToken
;
import
com.yd.auth.core.dto.LoginRequest
;
import
com.yd.auth.core.dto.LoginResponse
;
import
com.yd.auth.core.security.JwtTokenProvider
;
import
com.yd.auth.core.service.AuthService
;
import
com.yd.auth.core.utils.JwtUtils
;
import
com.yd.user.service.entity.User
;
import
com.yd.user.service.service.UserService
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.security.authentication.AuthenticationManager
;
import
org.springframework.security.authentication.UsernamePasswordAuthenticationToken
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.stereotype.Service
;
import
java.util.HashMap
;
import
java.util.Map
;
@Service
public
class
AuthServiceImpl
implements
AuthService
{
@Autowired
private
AuthenticationManager
authenticationManager
;
@Autowired
private
JwtUtils
jwtUtils
;
private
final
AuthenticationManager
authenticationManager
;
private
final
JwtTokenProvider
jwtTokenProvider
;
@Autowired
private
UserService
userService
;
public
AuthServiceImpl
(
AuthenticationManager
authenticationManager
,
JwtTokenProvider
jwtTokenProvider
)
{
this
.
authenticationManager
=
authenticationManager
;
this
.
jwtTokenProvider
=
jwtTokenProvider
;
}
@Override
public
Map
<
String
,
String
>
login
(
String
username
,
String
password
)
{
// 验证用户名和密码
Authentication
authentication
=
authenticationManager
.
authenticate
(
new
UsernamePasswordAuthenticationToken
(
username
,
password
)
public
LoginResponse
login
(
LoginRequest
loginRequest
)
{
// 1. 创建认证对象
Authentication
authentication
=
new
UsernamePasswordAuthenticationToken
(
loginRequest
.
getUsername
(),
loginRequest
.
getPassword
()
);
// 将认证信息设置到SecurityContext中
SecurityContextHolder
.
getContext
().
setAuthentication
(
authentication
);
// 获取用户信息
UserDetails
userDetails
=
(
UserDetails
)
authentication
.
getPrincipal
();
// 生成JWT令牌
String
token
=
jwtUtils
.
generateToken
(
userDetails
);
String
refreshToken
=
jwtUtils
.
generateRefreshToken
(
userDetails
);
// 2. 进行认证
Authentication
authenticated
=
authenticationManager
.
authenticate
(
authentication
);
// 返回令牌
Map
<
String
,
String
>
result
=
new
HashMap
<
String
,
String
>();
result
.
put
(
"token"
,
token
);
result
.
put
(
"refreshToken"
,
refreshToken
);
return
result
;
}
@Override
public
Map
<
String
,
String
>
refreshToken
(
String
refreshToken
)
{
// 验证刷新令牌
if
(!
jwtUtils
.
validateToken
(
refreshToken
))
{
throw
new
RuntimeException
(
"无效的刷新令牌"
);
}
// 获取用户名
String
username
=
jwtUtils
.
getUsernameFromToken
(
refreshToken
);
// 3. 设置安全上下文
SecurityContextHolder
.
getContext
().
setAuthentication
(
authenticated
);
//
加载用户详情
UserDetails
userDetails
=
userService
.
loadUserByUsername
(
username
);
//
4. 生成令牌
String
token
=
jwtTokenProvider
.
generateToken
(
authenticated
);
// 生成新的JWT令牌
String
token
=
jwtUtils
.
generateToken
(
userDetails
);
// 5. 创建响应对象
LoginResponse
response
=
new
LoginResponse
();
response
.
setToken
(
token
);
response
.
setExpiresIn
(
jwtTokenProvider
.
getJwtExpiration
());
// 返回新令牌
Map
<
String
,
String
>
result
=
new
HashMap
<
String
,
String
>();
result
.
put
(
"token"
,
token
);
result
.
put
(
"refreshToken"
,
refreshToken
);
return
result
;
return
response
;
}
@Override
public
Authentication
validateToken
(
String
token
)
{
JwtAuthenticationToken
authentication
=
new
JwtAuthenticationToken
(
token
);
return
authenticationManager
.
authenticate
(
authentication
);
public
void
logout
(
String
token
)
{
// 实现令牌失效逻辑(可选)
// 实际应用中可能需要将令牌加入黑名单
SecurityContextHolder
.
clearContext
();
}
@Override
public
User
register
(
User
user
)
{
return
userService
.
register
(
user
);
public
Authentication
getAuthentication
(
String
token
)
{
if
(
jwtTokenProvider
.
validateToken
(
token
))
{
return
jwtTokenProvider
.
getAuthentication
(
token
);
}
return
null
;
}
}
yd-auth-core/src/main/resources/banner.txt
0 → 100644
View file @
345cdf96
${AnsiColor.GREEN}
_ _ _ __ __ ____ _ _ _ _ _
| | (_)_ __ | | _\ \ / /__ / ___| |__ __ _| |_ / \ _ _| |_| |__
| | | | '_ \| |/ /\ \ /\ / / _ \ | | '_ \ / _` | __| / _ \| | | | __| '_ \
| |___| | | | | < \ V V / __/ |___| | | | (_| | |_ / ___ \ |_| | |_| | | |
|_____|_|_| |_|_|\_\ \_/\_/ \___|\____|_| |_|\__,_|\__/_/ \_\__,_|\__|_| |_|
${AnsiColor.BRIGHT_WHITE}
Spring Boot Version: ${spring-boot.version}
\ No newline at end of file
config
/bootstrap.yml
→
yd-auth-core/src/main/resources
/bootstrap.yml
View file @
345cdf96
...
...
@@ -40,7 +40,7 @@ spring:
# 配置中心
config
:
# 命名空间id(此处不用public,因public初始化的空间, id为空)
namespace
:
d2446fdc-2683-4c82-aa86-61242c61b5cd
namespace
:
c1e4cbcf-d8b7-4da9-a75a-7b75890fc390
# nacos的ip地址和端口
server-addr
:
139.224.145.34:8848
# 这个就表示 在我们nacos命名空间id为 dev中 有一个data-id 为 demo-service.yml 的配置文件 读取这个里面的配置
...
...
@@ -49,6 +49,11 @@ spring:
# 共享配置, 可以把公共配置放在同个命名空间下,然后创建一个 common.yml 文件 ,里面可以放共用的配置
shared-configs[0]
:
dataId
:
yd-common.yml
group
:
YD_GROUP
refresh
:
true
extension-configs
:
# 扩展配置
-
data-id
:
yd-auth-core.yml
group
:
YD_GROUP
refresh
:
true
# 发布到注册中心 (如果没有使用可以不配)
discovery
:
...
...
@@ -75,8 +80,9 @@ spring:
config-retry-time
:
300000
# 共享配置, 可以把公共配置放在同个命名空间下,然后创建一个 common.yml 文件 ,里面可以放共用的配置
shared-configs[0]
:
dataId
:
linkwe
-common.yml
dataId
:
yd
-common.yml
refresh
:
true
group
:
YD_GROUP
# 发布到注册中心 (如果没有使用可以不配)
discovery
:
# 命名空间id(此处不用public,因public初始化的空间, id为空)
...
...
yd-auth-core/src/main/resources/spy.properties
0 → 100644
View file @
345cdf96
#3.2.1以上使用
modulelist
=
com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
#3.2.1以下使用或者不配置
#modulelist=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat
=
com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender
=
com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers
=
true
# 取消JDBC URL前缀
useprefix
=
true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories
=
info,debug,result,commit,resultset
# 日期格式
dateformat
=
yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection
=
true
# 慢SQL记录标准 2 秒
outagedetectioninterval
=
2
#开启日志过滤
filter
=
true
#排序sql包含QRTZ的sql 多个逗号隔离
exclude
=
QRTZ,sys_oper_log
\ No newline at end of file
yd-common/pom.xml
View file @
345cdf96
...
...
@@ -28,7 +28,6 @@
<dependency>
<groupId>
org.projectlombok
</groupId>
<artifactId>
lombok
</artifactId>
<optional>
true
</optional>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
...
...
yd-framework/src/main/java/com/yd/framework/handler/GlobalExceptionHandler.java
View file @
345cdf96
...
...
@@ -9,6 +9,13 @@ import org.springframework.web.bind.MethodArgumentNotValidException;
import
org.springframework.web.bind.annotation.ExceptionHandler
;
import
org.springframework.web.bind.annotation.RestControllerAdvice
;
//import com.yd.common.model.R;
//import org.springframework.http.HttpStatus;
//import org.springframework.security.authentication.BadCredentialsException;
//import org.springframework.web.bind.annotation.ExceptionHandler;
//import org.springframework.web.bind.annotation.ResponseStatus;
//import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 全局异常处理器
*/
...
...
@@ -45,4 +52,16 @@ public class GlobalExceptionHandler {
log
.
error
(
"系统异常: "
,
e
);
return
Result
.
fail
(
"系统异常,请联系管理员"
);
}
// @ExceptionHandler(BadCredentialsException.class)
// @ResponseStatus(HttpStatus.UNAUTHORIZED)
// public R<?> handleBadCredentialsException(BadCredentialsException e) {
// return R.fail(401, "用户名或密码错误");
// }
//
// @ExceptionHandler(JwtTokenProvider.JwtAuthenticationException.class)
// @ResponseStatus(HttpStatus.UNAUTHORIZED)
// public R<?> handleJwtAuthenticationException(JwtTokenProvider.JwtAuthenticationException e) {
// return R.fail(401, e.getMessage());
// }
}
yd-gateway/src/main/java/com/yd/gateway/config/GatewaySecurityConfig.java
View file @
345cdf96
package
com
.
yd
.
gateway
.
config
;
import
com.yd.gateway.filter.AuthenticationFilter
;
import
com.yd.auth.core.security.JwtTokenProvider
;
import
com.yd.auth.core.security.JwtTokenProvider.JwtAuthenticationException
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.core.annotation.Order
;
import
org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity
;
import
org.springframework.security.config.web.server.SecurityWebFiltersOrder
;
import
org.springframework.security.config.web.server.ServerHttpSecurity
;
import
org.springframework.security.oauth2.jwt.Jwt
;
import
org.springframework.security.web.server.SecurityWebFilterChain
;
import
org.springframework.security.web.server.context.NoOpServerSecurityContextRepository
;
import
reactor.core.publisher.Mono
;
/**
* 网关安全配置
*/
@Configuration
@EnableWebFluxSecurity
public
class
GatewaySecurityConfig
{
private
final
AuthenticationFilter
authenticationFilt
er
;
private
final
JwtTokenProvider
jwtTokenProvid
er
;
public
GatewaySecurityConfig
(
AuthenticationFilter
authenticationFilt
er
)
{
this
.
authenticationFilter
=
authenticationFilt
er
;
public
GatewaySecurityConfig
(
JwtTokenProvider
jwtTokenProvid
er
)
{
this
.
jwtTokenProvider
=
jwtTokenProvid
er
;
}
@Bean
@Order
(-
1
)
public
SecurityWebFilterChain
securityWebFilterChain
(
ServerHttpSecurity
http
)
{
return
http
http
.
csrf
().
disable
()
.
securityContextRepository
(
NoOpServerSecurityContextRepository
.
getInstance
())
.
authorizeExchange
()
// 放行登录和刷新令牌接口
.
pathMatchers
(
"/auth/login"
,
"/auth/refresh-token"
).
permitAll
()
// 放行健康检查接口
.
pathMatchers
(
"/actuator/health/**"
).
permitAll
()
// 其他请求需要认证
.
anyExchange
().
authenticated
()
.
and
()
.
addFilterAt
(
authenticationFilter
,
SecurityWebFiltersOrder
.
AUTHENTICATION
)
.
build
();
.
authorizeExchange
(
exchanges
->
exchanges
.
pathMatchers
(
"/auth/**"
,
"/swagger-ui/**"
,
"/v3/api-docs/**"
).
permitAll
()
// 放行认证和Swagger路径
.
anyExchange
().
authenticated
()
// 其他请求需要认证
)
.
oauth2ResourceServer
(
oauth2
->
oauth2
.
jwt
(
jwt
->
jwt
.
jwtDecoder
(
token
->
{
try
{
// 验证令牌有效性
jwtTokenProvider
.
validateToken
(
token
);
// 将字符串转换为 Jwt 对象
Jwt
jwtObject
=
Jwt
.
withTokenValue
(
token
).
build
();
return
Mono
.
just
(
jwtObject
);
}
catch
(
JwtAuthenticationException
e
)
{
return
Mono
.
error
(
e
);
}
})
)
);
return
http
.
build
();
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment