Spring Cloud Gateway + JWT 单点登录实现方案
一、方案概述
本方案基于Spring Cloud微服务架构,通过网关统一认证和JWT令牌实现分布式系统的单点登录,移除了独立的认证服务器,简化架构同时保持安全性。核心技术组件包括:
- Spring Cloud Gateway:统一请求入口,负责认证、授权和路由转发
- JWT(Json Web Token):作为无状态令牌载体,包含用户身份和权限信息
- Spring Security:提供认证和授权功能,集成在网关层
- MyBatis-Plus
二、系统架构与服务组件
1. 服务架构图
+—————-+ +—————-+ +—————-+
| | | | | |
| 客户端应用 |<—>| API网关 |<—>| 用户资源服务 |
| (前端项目) | | (认证+路由) | | (user-service) |
| | | | | |
+—————-+ +——–+——-+ +——–+——-+
|
v
+—————-+ +—————-+
| | | |
| 订单资源服务 | | 产品资源服务 |
|(order-service) | |(product-service)|
| | | |
+—————-+ +—————-+
2. 服务职责说明
API网关 | 统一请求入口,处理用户登录、Token生成、验证和路由分发 |
资源服务 | 提供业务数据接口,依赖网关传递的Token进行权限控制 |
客户端应用 | 用户交互入口,通过API调用网关服务,处理登录状态和Token存储 |
三、核心技术实现
1. 网关服务配置文件(application.yml)
server:
port: 8080
spring:
application:
name: api–gateway
datasource:
url: jdbc:mysql://localhost:3306/sso_db?useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
security:
jwt:
secret: sso–jwt–secret–key
expiration: 3600
cloud:
gateway:
routes:
– id: user–service
uri: lb://user–service
predicates: Path=/api/users/**
filters: TokenRelay
– id: order–service
uri: lb://order–service
predicates: Path=/api/orders/**
filters: TokenRelay
– id: public–api
uri: lb://gateway
predicates: Path=/api/public/**
mybatis-plus:
mapper-locations: classpath*:/mapper/**/*.xml
type-aliases-package: com.example.gateway.model
configuration:
map-underscore-to-camel-case: true
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
db-config:
id-type: auto
2. 数据实体类(User.java)
@Data
@TableName(\”sys_user\”)
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String username;
private String password;
private String realName;
private String phone;
private Date createTime;
// 权限列表(实际项目中建议单独建表)
private String permissions;
}
3. 数据访问层(UserMapper.java)
@Mapper
public interface UserMapper extends BaseMapper<User> {
User selectByUsername(String username);
}
4. 服务层实现(UserDetailsServiceImpl.java)
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userMapper.selectByUsername(username);
if (user == null) {
throw new UsernameNotFoundException(\”用户不存在\”);
}
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
Collections.emptyList()
);
}
}
5. 网关安全配置(SecurityConfig.java)
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
@Autowired
private JwtRequestFilter jwtRequestFilter;
@Autowired
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
return authConfig.getAuthenticationManager();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests()
.antMatchers(\”/api/auth/**\”, \”/api/public/**\”).permitAll()
.anyRequest().authenticated();
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
6. JWT工具类(JwtUtils.java)
@Component
public class JwtUtils {
@Value(\”${spring.security.jwt.secret}\”)
private String secret;
@Value(\”${spring.security.jwt.expiration}\”)
private Long expiration;
public String extractUsername(String token) {
return extractClaim(token, Claims::getSubject);
}
public Date extractExpiration(String token) {
评论前必须登录!
注册