Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:oauth2 增加密码模式 #10663 #10703

Merged
merged 14 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.tencent.devops.auth.api.oauth2

import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest
import com.tencent.devops.auth.pojo.dto.ClientDetailsDTO
import com.tencent.devops.auth.pojo.dto.Oauth2AuthorizationCodeDTO
import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo
import com.tencent.devops.auth.pojo.vo.Oauth2AuthorizationInfoVo
Expand All @@ -13,6 +14,7 @@ import io.swagger.v3.oas.annotations.tags.Tag
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.Parameter
import javax.ws.rs.Consumes
import javax.ws.rs.DELETE
import javax.ws.rs.GET
import javax.ws.rs.HeaderParam
import javax.ws.rs.POST
Expand Down Expand Up @@ -70,9 +72,9 @@ interface Oauth2ServiceEndpointResource {
clientSecret: String,
@Parameter(description = "oauth2获取token请求报文体", required = true)
accessTokenRequest: Oauth2AccessTokenRequest
): Result<Oauth2AccessTokenVo?>
): Result<Oauth2AccessTokenVo>

@POST
@GET
@Path("/verifyAccessToken")
@Operation(summary = "校验accessToken")
fun verifyAccessToken(
Expand All @@ -86,4 +88,21 @@ interface Oauth2ServiceEndpointResource {
@Parameter(description = "access token", required = true)
accessToken: String
): Result<String>

@POST
@Path("/createClientDetails")
@Operation(summary = "新增Oauth2客户端信息")
fun createClientDetails(
@Parameter(description = "Oauth2客户端请求实体", required = true)
clientDetailsDTO: ClientDetailsDTO
): Result<Boolean>

@DELETE
@Path("/deleteClientDetails")
@Operation(summary = "删除Oauth2客户端信息")
fun deleteClientDetails(
@Parameter(description = "客户端ID", required = true)
@QueryParam("clientId")
clientId: String
): Result<Boolean>
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
package com.tencent.devops.auth.pojo

import com.fasterxml.jackson.annotation.JsonSubTypes
import com.fasterxml.jackson.annotation.JsonTypeInfo
import com.tencent.devops.auth.pojo.enum.Oauth2GrantType
import io.swagger.v3.oas.annotations.media.Schema

@Schema(title = "oauth2获取token请求报文体")
data class Oauth2AccessTokenRequest(
@get:Schema(title = "授权类型", required = true)
val grantType: String,
@get:Schema(title = "授权码,用于授权码模式", required = false)
val code: String? = null,
@get:Schema(title = "refreshToken,用于刷新授权码模式", required = false)
val refreshToken: String? = null
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY,
property = "grantType",
visible = true,
defaultImpl = Oauth2AccessTokenRequest::class
)
@JsonSubTypes(
JsonSubTypes.Type(value = Oauth2AuthorizationCodeRequest::class, name = Oauth2AuthorizationCodeRequest.TYPE),
JsonSubTypes.Type(value = Oauth2PassWordRequest::class, name = Oauth2PassWordRequest.TYPE),
JsonSubTypes.Type(value = Oauth2RefreshTokenRequest::class, name = Oauth2RefreshTokenRequest.TYPE)
)
interface Oauth2AccessTokenRequest {
@get:Schema(title = "授权类型", required = true)
open val grantType: Oauth2GrantType
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.tencent.devops.auth.pojo

import com.tencent.devops.auth.pojo.enum.Oauth2GrantType
import io.swagger.v3.oas.annotations.media.Schema

@Schema(title = "授权码模式获取token请求报文体")
data class Oauth2AuthorizationCodeRequest(
@get:Schema(title = "授权类型", required = true)
override val grantType: Oauth2GrantType,
@get:Schema(title = "授权码,用于授权码模式", required = false)
val code: String
) : Oauth2AccessTokenRequest {
companion object {
const val TYPE = "AUTHORIZATION_CODE"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.tencent.devops.auth.pojo

import com.tencent.devops.auth.pojo.enum.Oauth2GrantType
import io.swagger.v3.oas.annotations.media.Schema

@Schema(title = "密码模式获取token请求报文体")
data class Oauth2PassWordRequest(
@get:Schema(title = "授权类型", required = true)
override val grantType: Oauth2GrantType,
@get:Schema(title = "账号名称,用于密码模式", required = false)
val userName: String? = null,
@get:Schema(title = "密码,用于密码模式", required = false)
val passWord: String? = null
) : Oauth2AccessTokenRequest {
companion object {
const val TYPE = "PASS_WORD"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.tencent.devops.auth.pojo

import com.tencent.devops.auth.pojo.enum.Oauth2GrantType
import io.swagger.v3.oas.annotations.media.Schema

@Schema(title = "客户端模式获取token请求报文体")
data class Oauth2RefreshTokenRequest(
@get:Schema(title = "授权类型", required = true)
override val grantType: Oauth2GrantType,
@get:Schema(title = "刷新码,用于刷新授权码模式", required = false)
val refreshToken: String
) : Oauth2AccessTokenRequest {
companion object {
const val TYPE = "REFRESH_TOKEN"
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.tencent.devops.auth.pojo.dto

import com.tencent.devops.auth.pojo.enum.Oauth2GrantType
import io.swagger.v3.oas.annotations.media.Schema

@Schema(title = "Oauth2客户端请求实体")
Expand All @@ -15,15 +16,15 @@ data class ClientDetailsDTO(
@get:Schema(title = "图标")
val icon: String,
@get:Schema(title = "授权模式")
val authorizedGrantTypes: String,
val authorizedGrantTypes: List<Oauth2GrantType>,
@get:Schema(title = "跳转链接")
val webServerRedirectUri: String,
@get:Schema(title = "access_token有效时间")
val accessTokenValidity: Long,
@get:Schema(title = "refresh_token有效时间")
val refreshTokenValidity: Long,
@get:Schema(title = "创建人")
val createUser: String? = null,
val createUser: String = "system",
@get:Schema(title = "更新人")
val updateUser: String? = null
val updateUser: String = "system"
)
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ data class Oauth2AccessTokenDTO(
val expiredTime: Long? = null,
@get:Schema(title = "accessToken绑定的用户名称", required = true)
val userName: String? = null,
@get:Schema(title = "accessToken绑定的密码", required = true)
val passWord: String? = null,
@get:Schema(title = "授权范围Id", required = true)
val scopeId: Int
)
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ enum class Oauth2GrantType(val grantType: String) {
// 客户端模式
CLIENT_CREDENTIALS("client_credentials"),

// 密码模式
PASS_WORD("pass_word"),

// 刷新token模式
REFRESH_TOKEN("refresh_token");
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ class AuthOauth2AccessTokenDao {
accessToken: String? = null,
refreshToken: String? = null,
userName: String? = null,
passWord: String? = null,
Copy link
Member

Choose a reason for hiding this comment

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

密码需要加密存储

grantType: String? = null
): TAuthOauth2AccessTokenRecord? {
return with(TAuthOauth2AccessToken.T_AUTH_OAUTH2_ACCESS_TOKEN) {
dslContext.selectFrom(this)
.where(CLIENT_ID.eq(clientId))
.apply { accessToken?.let { and(ACCESS_TOKEN.eq(it)) } }
.apply { userName?.let { and(USER_NAME.eq(it)) } }
.apply { passWord?.let { and(PASS_WORD.eq(it)) } }
.apply { grantType?.let { and(GRANT_TYPE.eq(it)) } }
.apply { refreshToken?.let { and(REFRESH_TOKEN.eq(it)) } }
.fetchOne()
Expand All @@ -43,6 +45,7 @@ class AuthOauth2AccessTokenDao {
dslContext: DSLContext,
clientId: String,
userName: String?,
passWord: String?,
grantType: String,
accessToken: String,
refreshToken: String? = null,
Expand All @@ -54,6 +57,7 @@ class AuthOauth2AccessTokenDao {
this,
CLIENT_ID,
USER_NAME,
PASS_WORD,
GRANT_TYPE,
ACCESS_TOKEN,
REFRESH_TOKEN,
Expand All @@ -62,6 +66,7 @@ class AuthOauth2AccessTokenDao {
).values(
clientId,
userName,
passWord,
grantType,
accessToken,
refreshToken,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class AuthOauth2ClientDetailsDao {
clientDetailsDTO.clientName,
clientDetailsDTO.scope,
clientDetailsDTO.icon,
clientDetailsDTO.authorizedGrantTypes,
clientDetailsDTO.authorizedGrantTypes.map { it.grantType }.joinToString { "," },
clientDetailsDTO.webServerRedirectUri,
clientDetailsDTO.accessTokenValidity,
clientDetailsDTO.refreshTokenValidity,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@ package com.tencent.devops.auth.resources

import com.tencent.devops.auth.api.oauth2.Oauth2ServiceEndpointResource
import com.tencent.devops.auth.pojo.Oauth2AccessTokenRequest
import com.tencent.devops.auth.pojo.dto.ClientDetailsDTO
import com.tencent.devops.auth.pojo.dto.Oauth2AuthorizationCodeDTO
import com.tencent.devops.auth.pojo.vo.Oauth2AccessTokenVo
import com.tencent.devops.auth.pojo.vo.Oauth2AuthorizationInfoVo
import com.tencent.devops.auth.service.oauth2.Oauth2ClientService
import com.tencent.devops.auth.service.oauth2.Oauth2EndpointService
import com.tencent.devops.common.api.pojo.Result
import com.tencent.devops.common.web.RestResource

@RestResource
class Oauth2ServiceEndpointResourceImpl constructor(
private val endpointService: Oauth2EndpointService
class Oauth2ServiceEndpointResourceImpl(
private val endpointService: Oauth2EndpointService,
private val clientService: Oauth2ClientService
) : Oauth2ServiceEndpointResource {
override fun getAuthorizationInformation(
userId: String,
Expand Down Expand Up @@ -47,7 +50,7 @@ class Oauth2ServiceEndpointResourceImpl constructor(
clientId: String,
clientSecret: String,
accessTokenRequest: Oauth2AccessTokenRequest
): Result<Oauth2AccessTokenVo?> {
): Result<Oauth2AccessTokenVo> {
return Result(
endpointService.getAccessToken(
clientId = clientId,
Expand All @@ -70,4 +73,18 @@ class Oauth2ServiceEndpointResourceImpl constructor(
)
)
}

override fun createClientDetails(clientDetailsDTO: ClientDetailsDTO): Result<Boolean> {
return Result(
clientService.createClientDetails(
clientDetailsDTO = clientDetailsDTO
)
)
}

override fun deleteClientDetails(clientId: String): Result<Boolean> {
return Result(
clientService.deleteClientDetails(clientId = clientId)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import org.jooq.DSLContext
import org.springframework.stereotype.Service

@Service
class Oauth2AccessTokenService constructor(
class Oauth2AccessTokenService(
private val oauth2AccessTokenDao: AuthOauth2AccessTokenDao,
private val dslContext: DSLContext
) {
Expand All @@ -31,13 +31,15 @@ class Oauth2AccessTokenService constructor(
clientId: String,
refreshToken: String? = null,
userName: String? = null,
passWord: String? = null,
grantType: String? = null
): TAuthOauth2AccessTokenRecord? {
return oauth2AccessTokenDao.get(
dslContext = dslContext,
clientId = clientId,
refreshToken = refreshToken,
userName = userName,
passWord = passWord,
grantType = grantType
)
}
Expand All @@ -46,6 +48,7 @@ class Oauth2AccessTokenService constructor(
fun create(
clientId: String,
userName: String?,
passWord: String?,
grantType: String,
accessToken: String,
refreshToken: String?,
Expand All @@ -56,6 +59,7 @@ class Oauth2AccessTokenService constructor(
dslContext = dslContext,
clientId = clientId,
userName = userName,
passWord = passWord,
grantType = grantType,
accessToken = accessToken,
refreshToken = refreshToken,
Expand Down

This file was deleted.

Loading
Loading