Skip to content

Feature/user auth guest mode feat: 添加用户认证访客模式和完善登录功能#6

Open
xiaoshuai155vv wants to merge 2 commits intomainfrom
feature/user-auth-guest-mode
Open

Feature/user auth guest mode feat: 添加用户认证访客模式和完善登录功能#6
xiaoshuai155vv wants to merge 2 commits intomainfrom
feature/user-auth-guest-mode

Conversation

@xiaoshuai155vv
Copy link
Collaborator

User Service: 访客登录、GitHub OAuth 修复、SecurityConfig
Gateway: 完整路由配置
前端: 登录页深色主题、未登录跳转、API 拦截器
文档: 设计文档、实施计划、使用指南

21048313 and others added 2 commits February 22, 2026 11:27
- 新增访客登录功能 (POST /api/auth/guest),支持邮箱/手机号快速登录
- 访客用户自动创建,角色为 guest,无需注册
- 修复 GitHub OAuth 回调 500 错误,使用 generateTokenForUser 直接生成 Token
- 前端登录页添加深色主题,与 Dashboard 页面风格一致
- 未登录访问首页自动跳转到 /login
- Gateway 添加 User Service 和 Web IDE Backend 完整路由配置
- 后端 SecurityConfig 信任 Gateway 注入的 X-User-Id 等头信息
- 新增前端 API 拦截器统一处理 401/403 错误

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 新增 Gateway 服务完整的 JWT 认证路由配置
- 新增 User Service 微服务基础架构(Controller, Service, Repository, Entity)
- 新增 Docker 配置文件(Dockerfile, docker-compose)
- 完善后端 SecurityConfig 信任 Gateway 注入的用户信息
- 新增数据库迁移脚本(Flyway)
- 新增 JWT 认证过滤器(Gateway + User Service)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @xiaoshuai155vv, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

本次拉取请求引入了 Forge 平台的全新用户认证和授权系统,核心是新增了一个独立的 User Service,支持访客模式、本地账号、Keycloak SSO 和 GitHub OAuth 等多种登录方式。同时,API Gateway 得到了全面配置,负责统一路由和 JWT 验证,前端也进行了相应更新,包括登录页面的深色主题和未登录重定向,并引入了 API 拦截器以增强用户体验和安全性。此外,还提供了详尽的设计、实施和使用文档,确保了新功能的完整性和可维护性。

Highlights

  • 访客模式与多源登录: 实现了用户认证的访客模式,并完善了登录功能,支持本地账号、Keycloak SSO 和 GitHub OAuth 等多种登录方式。
  • 新增用户服务 (User Service): 引入了一个全新的独立用户服务,专门负责用户管理、权限控制和组织管理。
  • API Gateway 统一认证与路由: 全面配置了 API Gateway,用于统一路由请求并处理 JWT 认证,确保后端服务的安全访问。
  • 前端用户体验优化: 前端登录页面更新为深色主题,增加了未登录自动跳转功能,并引入了 API 拦截器以增强用户体验和安全性。
  • 完善的文档支持: 新增了详细的设计文档、实施计划和用户指南,为新功能的理解、部署和使用提供了全面的支持。
Changelog
  • build-user-service.bat
    • Added a new batch script for building the user service.
  • docs/user_auth/account-auth-sso-design.md
    • Added a comprehensive design document for account authentication and SSO architecture.
  • docs/user_auth/account-auth-sso-implementation-plan.md
    • Added a detailed implementation plan for the SSO and authentication features.
  • docs/user_auth/user-service-guide.md
    • Added a user guide for the new user service, including quick start, API documentation, and deployment.
  • infrastructure/docker/docker-compose.trial.yml
    • Modified Docker Compose configuration to include Redis and the new user service.
  • infrastructure/docker/docker-compose.yml
    • Updated the main Docker Compose file to integrate the new user service, API Gateway, and Redis.
  • infrastructure/docker/nginx-trial.conf
    • Modified Nginx configuration to support direct access to user service APIs and added comments for Gateway integration.
  • services/gateway/Dockerfile
    • Added Dockerfile for building the API Gateway service.
  • services/gateway/build.gradle.kts
    • Added Gradle build configuration for the API Gateway service.
  • services/gateway/src/main/kotlin/com/forge/gateway/GatewayApplication.kt
    • Added the main application class for the API Gateway.
  • services/gateway/src/main/kotlin/com/forge/gateway/config/AppConfig.kt
    • Added application configuration properties for the API Gateway.
  • services/gateway/src/main/kotlin/com/forge/gateway/config/GatewayConfig.kt
    • Added Gateway routing configuration, including JWT authentication filter.
  • services/gateway/src/main/kotlin/com/forge/gateway/filter/JwtAuthenticationFilter.kt
    • Added a JWT authentication filter for the API Gateway.
  • services/gateway/src/main/resources/application.yml
    • Added application properties for the API Gateway service.
  • services/user-service/Dockerfile
    • Added Dockerfile for building the user service.
  • services/user-service/build.gradle.kts
    • Added Gradle build configuration for the user service.
  • services/user-service/src/main/kotlin/com/forge/user/UserServiceApplication.kt
    • Added the main application class for the user service.
  • services/user-service/src/main/kotlin/com/forge/user/config/AppConfig.kt
    • Added application configuration properties for the user service.
  • services/user-service/src/main/kotlin/com/forge/user/config/DatabaseConfig.kt
    • Added database configuration for the user service.
  • services/user-service/src/main/kotlin/com/forge/user/config/DatabaseInitializationConfig.kt
    • Added database initialization logic, including default admin user creation.
  • services/user-service/src/main/kotlin/com/forge/user/config/JacksonConfig.kt
    • Added Jackson configuration for JSON serialization.
  • services/user-service/src/main/kotlin/com/forge/user/config/PasswordConfig.kt
    • Added password encoder configuration.
  • services/user-service/src/main/kotlin/com/forge/user/config/RedisConfig.kt
    • Added Redis configuration for the user service.
  • services/user-service/src/main/kotlin/com/forge/user/config/WebConfig.kt
    • Added web MVC configuration with a permission interceptor.
  • services/user-service/src/main/kotlin/com/forge/user/controller/AuthController.kt
    • Added authentication controller with endpoints for register, login, refresh, logout, and guest login.
  • services/user-service/src/main/kotlin/com/forge/user/controller/OAuthController.kt
    • Added OAuth controller for GitHub authentication flow.
  • services/user-service/src/main/kotlin/com/forge/user/controller/OrganizationController.kt
    • Added organization controller for CRUD operations and member management.
  • services/user-service/src/main/kotlin/com/forge/user/controller/UserController.kt
    • Added user controller for managing user profiles and searching.
  • services/user-service/src/main/kotlin/com/forge/user/dto/UserDto.kt
    • Added data transfer objects (DTOs) for user-related requests and responses.
  • services/user-service/src/main/kotlin/com/forge/user/entity/LoginLogEntity.kt
    • Added entity for storing login logs.
  • services/user-service/src/main/kotlin/com/forge/user/entity/OrgMemberEntity.kt
    • Added entity for organization members.
  • services/user-service/src/main/kotlin/com/forge/user/entity/OrganizationEntity.kt
    • Added entity for organizations.
  • services/user-service/src/main/kotlin/com/forge/user/entity/PermissionEntity.kt
    • Added entity for permissions.
  • services/user-service/src/main/kotlin/com/forge/user/entity/RolePermissionEntity.kt
    • Added entity for role-permission associations.
  • services/user-service/src/main/kotlin/com/forge/user/entity/UserEntity.kt
    • Added entity for user data.
  • services/user-service/src/main/kotlin/com/forge/user/entity/UserIdentityEntity.kt
    • Added entity for third-party user identities.
  • services/user-service/src/main/kotlin/com/forge/user/entity/UserRoleEntity.kt
    • Added entity for user roles.
  • services/user-service/src/main/kotlin/com/forge/user/exception/GlobalExceptionHandler.kt
    • Added global exception handler for the user service.
  • services/user-service/src/main/kotlin/com/forge/user/exception/UserException.kt
    • Added custom exception classes for user-related errors.
  • services/user-service/src/main/kotlin/com/forge/user/repository/OrgMemberRepository.kt
    • Added repository for organization members.
  • services/user-service/src/main/kotlin/com/forge/user/repository/OrganizationRepository.kt
    • Added repository for organizations.
  • services/user-service/src/main/kotlin/com/forge/user/repository/PermissionRepository.kt
    • Added repository for permissions.
  • services/user-service/src/main/kotlin/com/forge/user/repository/RolePermissionRepository.kt
    • Added repository for role-permission associations.
  • services/user-service/src/main/kotlin/com/forge/user/repository/UserIdentityRepository.kt
    • Added repository for user identities.
  • services/user-service/src/main/kotlin/com/forge/user/repository/UserRepository.kt
    • Added repository for user data.
  • services/user-service/src/main/kotlin/com/forge/user/repository/UserRoleRepository.kt
    • Added repository for user roles.
  • services/user-service/src/main/kotlin/com/forge/user/security/JwtAuthenticationFilter.kt
    • Added JWT authentication filter for the user service.
  • services/user-service/src/main/kotlin/com/forge/user/security/PermissionInterceptor.kt
    • Added permission interceptor for role-based access control.
  • services/user-service/src/main/kotlin/com/forge/user/security/RequirePermission.kt
    • Added annotation for requiring specific permissions.
  • services/user-service/src/main/kotlin/com/forge/user/security/SecurityConfig.kt
    • Added Spring Security configuration for the user service.
  • services/user-service/src/main/kotlin/com/forge/user/service/AuthService.kt
    • Added authentication service for user registration, login, and token management.
  • services/user-service/src/main/kotlin/com/forge/user/service/GithubOAuthService.kt
    • Added service for handling GitHub OAuth authentication.
  • services/user-service/src/main/kotlin/com/forge/user/service/IdentityService.kt
    • Added service for managing third-party user identities.
  • services/user-service/src/main/kotlin/com/forge/user/service/JwtService.kt
    • Added service for JWT token generation and validation.
  • services/user-service/src/main/kotlin/com/forge/user/service/OrganizationService.kt
    • Added service for managing organizations and members.
  • services/user-service/src/main/kotlin/com/forge/user/service/PermissionService.kt
    • Added service for managing and checking user permissions.
  • services/user-service/src/main/kotlin/com/forge/user/service/UserService.kt
    • Added core user service for CRUD operations and guest user creation.
  • services/user-service/src/main/resources/application.yml
    • Added application properties for the user service.
  • services/user-service/src/main/resources/db/migration/V1__init_user_schema.sql
    • Added Flyway migration script for initial user and organization schema.
  • services/user-service/src/main/resources/db/migration/V2__init_permissions.sql
    • Added Flyway migration script for initial permission data.
  • services/user-service/src/main/resources/db/migration/V3__fix_ip_column_type.sql
    • Added Flyway migration script to fix IP address column types.
  • services/user-service/src/main/resources/db/migration/V4__change_jsonb_to_text.sql
    • Added Flyway migration script to change JSONB columns to TEXT.
  • services/user-service/src/main/resources/logback-spring.xml
    • Added Logback configuration for the user service.
  • settings.gradle.kts
    • Updated Gradle settings to include new user service and gateway modules.
  • web-ide/backend/src/main/kotlin/com/forge/webide/config/SecurityConfig.kt
    • Modified backend security configuration to integrate with the new Gateway authentication.
  • web-ide/frontend/next.config.ts
    • Modified Next.js configuration to disable Turbopack and update API rewrite rules for Gateway integration.
  • web-ide/frontend/package-lock.json
    • Updated package lock file to reflect dependency changes, including TypeScript version.
  • web-ide/frontend/package.json
    • Updated frontend dependencies, including a TypeScript version bump.
  • web-ide/frontend/src/app/auth/callback/page.tsx
    • Modified authentication callback page to handle both Keycloak and GitHub OAuth.
  • web-ide/frontend/src/app/login/page.tsx
    • Modified login page to use the new LoginForm component and SSO client.
  • web-ide/frontend/src/app/page.tsx
    • Modified dashboard page to enforce authentication and redirect unauthenticated users to login.
  • web-ide/frontend/src/components/auth/LoginForm.tsx
    • Added a new React component for the unified login form, supporting various authentication methods.
  • web-ide/frontend/src/lib/api-interceptor.ts
    • Added a new API interceptor for handling authentication, token refresh, and error redirection.
  • web-ide/frontend/src/lib/sso-client.ts
    • Added a new SSO client library to manage authentication flows for Keycloak, local accounts, GitHub, and guest mode.
  • web-ide/frontend/tsconfig.json
    • Updated TypeScript configuration to include new types and adjust library settings.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This PR successfully implements user authentication's guest mode and improves login functionality, covering the complete chain from backend User Service to Gateway routing and frontend integration, adopting an RBAC model and supporting multiple identity sources. However, a critical authentication bypass vulnerability exists where internal services trust identity headers without source verification, potentially leading to impersonation. Additionally, the OrganizationController lacks permission checks, and several hardcoded secrets, insecure CORS configurations, and incomplete brute force protection logic were identified. There are also hardcoding issues (e.g., gateway service address, token refresh user info) and potential risks from manually constructing JSON strings. It is recommended to address these issues to enhance security, maintainability, and adaptability.

Comment on lines +48 to +78
val xUserId = request.getHeader(HEADER_USER_ID)
val userAccount = request.getHeader(HEADER_USER_ACCOUNT)
val xUserRoles = request.getHeader(HEADER_USER_ROLES)

// 优先从 user-account JSON 解析
if (!userAccount.isNullOrBlank()) {
try {
val userNode = objectMapper.readTree(userAccount)
val userId = userNode.get("userId")?.asText() ?: xUserId
val username = userNode.get("username")?.asText() ?: ""
val rolesNode = userNode.get("roles")
val roles = if (rolesNode != null && rolesNode.isArray) {
rolesNode.map { it.asText() }
} else {
xUserRoles?.split(",")?.filter { it.isNotBlank() } ?: listOf("user")
}

setAuthentication(userId, username, roles, request)
} catch (e: Exception) {
// JSON 解析失败,尝试从单独的头读取
if (!xUserId.isNullOrBlank()) {
val roles = xUserRoles?.split(",")?.filter { it.isNotBlank() } ?: listOf("user")
setAuthentication(xUserId, "", roles, request)
}
}
}
// 其次从 X-User-Id 头读取
else if (!xUserId.isNullOrBlank()) {
val roles = xUserRoles?.split(",")?.filter { it.isNotBlank() } ?: listOf("user")
setAuthentication(xUserId, "", roles, request)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-critical critical

The JwtAuthenticationFilter trusts identity headers (X-User-Id, user-account, X-User-Roles) to establish the security context for a request. These headers are intended to be injected by the API Gateway after it validates a JWT. However, the service does not verify that the request actually originated from the trusted Gateway. If an attacker can reach this service directly, they can spoof these headers to impersonate any user and assume any role, including admin.

Comment on lines +120 to +152
override fun doFilter(request: jakarta.servlet.ServletRequest, response: jakarta.servlet.ServletResponse, chain: jakarta.servlet.FilterChain) {
val httpRequest = request as HttpServletRequest

val xUserId = httpRequest.getHeader(SecurityConfig.HEADER_USER_ID)
val userAccount = httpRequest.getHeader(SecurityConfig.HEADER_USER_ACCOUNT)
val xUserRoles = httpRequest.getHeader(SecurityConfig.HEADER_USER_ROLES)

// 如果有 Gateway 注入的用户信息,设置认证
if (!userAccount.isNullOrBlank()) {
try {
val userNode = objectMapper.readTree(userAccount)
val userId = userNode.get("userId")?.asText() ?: xUserId
val rolesNode = userNode.get("roles")
val roles = if (rolesNode != null && rolesNode.isArray) {
rolesNode.map { SimpleGrantedAuthority("ROLE_${it.asText().uppercase()}") }
} else {
parseRoles(xUserRoles)
}

val authentication = UsernamePasswordAuthenticationToken(userId, null, roles)
SecurityContextHolder.getContext().authentication = authentication
} catch (e: Exception) {
// 解析失败,静默忽略,让后续 JWT 验证处理
}
} else if (!xUserId.isNullOrBlank()) {
// 只有 X-User-Id,使用默认角色
val roles = parseRoles(xUserRoles)
val authentication = UsernamePasswordAuthenticationToken(xUserId, null, roles)
SecurityContextHolder.getContext().authentication = authentication
}

chain.doFilter(request, response)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-critical critical

The GatewayAuthenticationFilter trusts identity headers (X-User-Id, user-account, X-User-Roles) to establish the security context. It does not verify that these headers come from a trusted source. Furthermore, since this filter is added before the JWT validation filter, an attacker can bypass JWT validation entirely by providing a spoofed user-account header.

class JwtAuthenticationFilter : AbstractGatewayFilterFactory<JwtAuthenticationFilter.Config>(Config::class.java) {

companion object {
private const val DEFAULT_JWT_SECRET = "your_jwt_secret_key_at_least_32_chars_here"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

硬编码默认的 JWT 密钥是一个严重的安全风险。如果环境变量 JWT_SECRET 未设置,系统将回退到这个已知的密钥,从而允许攻击者伪造 Token。建议移除默认值,并确保在密钥缺失时应用启动失败。

Comment on lines +34 to +191
@Valid @RequestBody request: CreateOrgRequest,
@RequestHeader("X-User-Id") userId: String
): ResponseEntity<ApiResponse<OrgResponse>> {
return try {
val org = organizationService.createOrganization(
name = request.name,
ownerId = UUID.fromString(userId),
slug = request.slug,
description = request.description
)
ResponseEntity
.status(HttpStatus.CREATED)
.body(ApiResponse.success(OrgResponse.from(org), "组织创建成功"))
} catch (e: Exception) {
ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(ApiResponse.error(e.message ?: "创建失败"))
}
}

/**
* 获取组织详情
* GET /api/orgs/{id}
*/
@GetMapping("/{id}")
fun getOrganization(
@PathVariable id: String,
@RequestHeader("X-User-Id") userId: String
): ResponseEntity<ApiResponse<OrgResponse>> {
return try {
val org = organizationService.getOrganization(UUID.fromString(id))
ResponseEntity.ok(ApiResponse.success(OrgResponse.from(org)))
} catch (e: Exception) {
ResponseEntity
.status(HttpStatus.NOT_FOUND)
.body(ApiResponse.error("组织不存在"))
}
}

/**
* 获取用户所属组织列表
* GET /api/orgs
*/
@GetMapping
fun getMyOrganizations(
@RequestHeader("X-User-Id") userId: String
): ResponseEntity<ApiResponse<List<OrgResponse>>> {
return try {
val orgs = organizationService.getOrganizationsByUserId(UUID.fromString(userId))
ResponseEntity.ok(ApiResponse.success(orgs.map { OrgResponse.from(it) }))
} catch (e: Exception) {
ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ApiResponse.error("获取组织列表失败"))
}
}

/**
* 添加组织成员
* POST /api/orgs/{id}/members
*/
data class AddMemberRequest(
val userId: String,
val role: OrgRole = OrgRole.MEMBER
)

@PostMapping("/{id}/members")
fun addMember(
@PathVariable id: String,
@Valid @RequestBody request: AddMemberRequest,
@RequestHeader("X-User-Id") currentUserId: String
): ResponseEntity<ApiResponse<Unit>> {
return try {
organizationService.addMember(
orgId = UUID.fromString(id),
userId = UUID.fromString(request.userId),
role = request.role,
invitedBy = UUID.fromString(currentUserId)
)
ResponseEntity.ok(ApiResponse.success(message = "成员添加成功"))
} catch (e: Exception) {
ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(ApiResponse.error(e.message ?: "添加成员失败"))
}
}

/**
* 移除组织成员
* DELETE /api/orgs/{id}/members/{userId}
*/
@DeleteMapping("/{id}/members/{userId}")
fun removeMember(
@PathVariable id: String,
@PathVariable userId: String,
@RequestHeader("X-User-Id") currentUserId: String
): ResponseEntity<ApiResponse<Unit>> {
return try {
organizationService.removeMember(
orgId = UUID.fromString(id),
userId = UUID.fromString(userId)
)
ResponseEntity.ok(ApiResponse.success(message = "成员移除成功"))
} catch (e: Exception) {
ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(ApiResponse.error(e.message ?: "移除成员失败"))
}
}

/**
* 更新成员角色
* PUT /api/orgs/{id}/members/{userId}/role
*/
data class UpdateRoleRequest(
val role: OrgRole
)

@PutMapping("/{id}/members/{userId}/role")
fun updateMemberRole(
@PathVariable id: String,
@PathVariable userId: String,
@Valid @RequestBody request: UpdateRoleRequest,
@RequestHeader("X-User-Id") currentUserId: String
): ResponseEntity<ApiResponse<Unit>> {
return try {
organizationService.updateMemberRole(
orgId = UUID.fromString(id),
userId = UUID.fromString(userId),
newRole = request.role
)
ResponseEntity.ok(ApiResponse.success(message = "角色更新成功"))
} catch (e: Exception) {
ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(ApiResponse.error(e.message ?: "更新角色失败"))
}
}

/**
* 获取组织成员列表
* GET /api/orgs/{id}/members
*/
@GetMapping("/{id}/members")
fun getMembers(
@PathVariable id: String,
@RequestHeader("X-User-Id") userId: String
): ResponseEntity<ApiResponse<List<MemberResponse>>> {
return try {
val members = organizationService.getMembers(UUID.fromString(id))
ResponseEntity.ok(ApiResponse.success(members.map { MemberResponse.from(it) }))
} catch (e: Exception) {
ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ApiResponse.error("获取成员列表失败"))
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-high high

The OrganizationController lacks authorization checks on sensitive endpoints such as createOrganization, addMember, removeMember, and updateMemberRole. The application uses a PermissionInterceptor that enforces permissions only when the @RequirePermission annotation is present on a handler method. Since these methods lack the annotation, any authenticated user can perform these actions on any organization, provided they know the organization and user IDs.

Comment on lines +16 to +17
private const val USER_SERVICE_URL = "http://localhost:8086"
private const val WEB_IDE_BACKEND_URL = "http://localhost:8080"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

在网关配置中硬编码了 localhost 地址。在 Docker 容器化部署环境中,这会导致网关无法连接到其他服务(因为 localhost 指向网关容器自身)。建议将这些地址提取到配置文件中,或者在 Docker 环境下使用服务名称(如 http://forge-user-service:8086)。

// 默认管理员配置
const val DEFAULT_ADMIN_USERNAME = "admin"
const val DEFAULT_ADMIN_EMAIL = "admin@forge.local"
const val DEFAULT_ADMIN_PASSWORD = "ForgeAdmin123!"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

A default administrator account is created with a hardcoded password (ForgeAdmin123!). Hardcoding default credentials in the source code is a significant security risk, as they are often left unchanged in production. It is recommended to manage such sensitive information through environment variables or configuration files to avoid exposing it directly in the source code.

Comment on lines +17 to +20
allowed-origins-patterns: "*"
allowed-methods: GET,POST,PUT,DELETE,OPTIONS
allowed-headers: "*"
allow-credentials: true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The CORS configuration allows all origins via allowed-origins-patterns: "*" while also enabling allow-credentials: true. This is an insecure configuration that allows any malicious website to make authenticated requests to the API on behalf of a logged-in user, potentially leading to CSRF attacks or data exfiltration.

Comment on lines +90 to +96
val failKey = "login:fail:${loggedInUser.id}"
val failCount = redisTemplate.opsForValue().get(failKey)?.toIntOrNull() ?: 0

if (failCount >= appConfig.security.maxLoginAttempts) {
recordLoginLog(loggedInUser.id.toString(), "password", ipAddress, false, "Too many attempts")
throw AuthenticationException("登录失败次数过多,请${appConfig.security.lockoutDurationMinutes}分钟后重试")
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The login method checks a failed login counter in Redis but never actually increments it when a password check fails. This renders the brute force protection logic ineffective.

Comment on lines +49 to +50
secret: ${JWT_SECRET:your_jwt_secret_key_at_least_32_chars_here}
refresh-secret: ${JWT_REFRESH_SECRET:your_jwt_refresh_secret_key_at_least_32_chars}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The application contains hardcoded default values for JWT secrets. If the JWT_SECRET environment variable is not provided, the system falls back to these insecure, publicly known strings for signing and verifying tokens.

return try {
// 从请求头获取用户信息,实际实现中应该调用 UserService
ResponseEntity.ok(ApiResponse.success(null))
} catch (e: Exception) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

/api/auth/me 接口目前直接返回 null 数据。作为完善登录功能的一部分,建议完成此功能的实现,通过 userService 获取并返回真实的用户信息。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant