| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 | package serviceimport (	"errors"	"github.com/dgrijalva/jwt-go"	"github.com/longjoy/micro-go-course/section32/model"	"time")var (	ErrExpiredToken        = errors.New("token is expired"))type ResourceServerTokenService interface {	// 根据访问令牌获取对应的用户信息和客户端信息	GetOAuth2DetailsByAccessToken(tokenValue string) (*model.OAuth2Details, error)}type DefaultTokenService struct {	tokenStore TokenStore	tokenEnhancer TokenEnhancer}func NewTokenService(tokenStore TokenStore, tokenEnhancer TokenEnhancer) ResourceServerTokenService {	return &DefaultTokenService{		tokenStore:tokenStore,		tokenEnhancer:tokenEnhancer,	}}func (tokenService *DefaultTokenService) GetOAuth2DetailsByAccessToken(tokenValue string) (*model.OAuth2Details, error) {	accessToken, err := tokenService.tokenStore.ReadAccessToken(tokenValue)	if err != nil{		return nil, err	}	if accessToken.IsExpired(){		return nil, ErrExpiredToken	}	return tokenService.tokenStore.ReadOAuth2Details(tokenValue)}type TokenStore interface {	// 存储访问令牌	StoreAccessToken(oauth2Token *model.OAuth2Token, oauth2Details *model.OAuth2Details) error	// 根据令牌值获取访问令牌结构体	ReadAccessToken(tokenValue string) (*model.OAuth2Token, error)	// 根据令牌值获取令牌对应的客户端和用户信息	ReadOAuth2Details(tokenValue string)(*model.OAuth2Details, error)	// 根据客户端信息和用户信息获取访问令牌	GetAccessToken(oauth2Details *model.OAuth2Details)(*model.OAuth2Token, error);	// 移除存储的访问令牌	RemoveAccessToken(tokenValue string) error	// 存储刷新令牌	StoreRefreshToken(oauth2Token *model.OAuth2Token, oauth2Details *model.OAuth2Details) error	// 移除存储的刷新令牌	RemoveRefreshToken(oauth2Token string) error	// 根据令牌值获取刷新令牌	ReadRefreshToken(tokenValue string)(*model.OAuth2Token, error)	// 根据令牌值获取刷新令牌对应的客户端和用户信息	ReadOAuth2DetailsForRefreshToken(tokenValue string)(*model.OAuth2Details, error)}func NewJwtTokenStore(jwtTokenEnhancer *JwtTokenEnhancer) TokenStore {	return &JwtTokenStore{		jwtTokenEnhancer:jwtTokenEnhancer,	}}type JwtTokenStore struct {	jwtTokenEnhancer *JwtTokenEnhancer}func (tokenStore *JwtTokenStore) StoreAccessToken(oauth2Token *model.OAuth2Token, oauth2Details *model.OAuth2Details) error{	return nil}func (tokenStore *JwtTokenStore)ReadAccessToken(tokenValue string) (*model.OAuth2Token, error){	oauth2Token, _, err := tokenStore.jwtTokenEnhancer.Extract(tokenValue)	return oauth2Token, err}// 根据令牌值获取令牌对应的客户端和用户信息func  (tokenStore *JwtTokenStore) ReadOAuth2Details(tokenValue string)(*model.OAuth2Details, error){	_, oauth2Details, err := tokenStore.jwtTokenEnhancer.Extract(tokenValue)	return oauth2Details, err}// 根据客户端信息和用户信息获取访问令牌func (tokenStore *JwtTokenStore) GetAccessToken(oauth2Details *model.OAuth2Details)(*model.OAuth2Token, error){	return nil, nil}// 移除存储的访问令牌func (tokenStore *JwtTokenStore) RemoveAccessToken(tokenValue string) error {	return nil}// 存储刷新令牌func (tokenStore *JwtTokenStore) StoreRefreshToken(oauth2Token *model.OAuth2Token, oauth2Details *model.OAuth2Details) error {	return nil}// 移除存储的刷新令牌func (tokenStore *JwtTokenStore)RemoveRefreshToken(oauth2Token string) error {	return nil}// 根据令牌值获取刷新令牌func (tokenStore *JwtTokenStore) ReadRefreshToken(tokenValue string)(*model.OAuth2Token, error){	oauth2Token, _, err := tokenStore.jwtTokenEnhancer.Extract(tokenValue)	return oauth2Token, err}// 根据令牌值获取刷新令牌对应的客户端和用户信息func (tokenStore *JwtTokenStore)ReadOAuth2DetailsForRefreshToken(tokenValue string)(*model.OAuth2Details, error){	_, oauth2Details, err := tokenStore.jwtTokenEnhancer.Extract(tokenValue)	return oauth2Details, err}type TokenEnhancer interface {	// 组装 Token 信息	Enhance(oauth2Token *model.OAuth2Token, oauth2Details *model.OAuth2Details) (*model.OAuth2Token, error)	// 从 Token 中还原信息	Extract(tokenValue string) (*model.OAuth2Token, *model.OAuth2Details, error)}type OAuth2TokenCustomClaims struct {	UserDetails model.UserDetails	ClientDetails model.ClientDetails	RefreshToken model.OAuth2Token	jwt.StandardClaims}type JwtTokenEnhancer struct {	secretKey []byte}func NewJwtTokenEnhancer(secretKey string) TokenEnhancer {	return &JwtTokenEnhancer{		secretKey:[]byte(secretKey),	}}func (enhancer *JwtTokenEnhancer) Enhance(oauth2Token *model.OAuth2Token, oauth2Details *model.OAuth2Details) (*model.OAuth2Token, error) {	return enhancer.sign(oauth2Token, oauth2Details)}func (enhancer *JwtTokenEnhancer) sign(oauth2Token *model.OAuth2Token, oauth2Details *model.OAuth2Details)  (*model.OAuth2Token, error) {	expireTime := oauth2Token.ExpiresTime	clientDetails := oauth2Details.Client	userDetails := oauth2Details.User	clientDetails.ClientSecret = ""	userDetails.Password = ""	claims := OAuth2TokenCustomClaims{		UserDetails:userDetails,		ClientDetails:clientDetails,		StandardClaims:jwt.StandardClaims{			ExpiresAt:expireTime.Unix(),			Issuer:"System",		},	}	if oauth2Token.RefreshToken != nil{		claims.RefreshToken = *oauth2Token.RefreshToken	}	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)	tokenValue, err := token.SignedString(enhancer.secretKey)	if err != nil{		return nil, err	}	oauth2Token.TokenValue = tokenValue	oauth2Token.TokenType = "jwt"	return oauth2Token, nil;}func (enhancer *JwtTokenEnhancer) Extract(tokenValue string) (*model.OAuth2Token, *model.OAuth2Details, error)  {	token, err := jwt.ParseWithClaims(tokenValue, &OAuth2TokenCustomClaims{}, func(token *jwt.Token) (i interface{}, e error) {		return enhancer.secretKey, nil	})	if err != nil{		return nil, nil, err	}	claims := token.Claims.(*OAuth2TokenCustomClaims)	expiresTime := time.Unix(claims.ExpiresAt, 0)	return &model.OAuth2Token{			RefreshToken:&claims.RefreshToken,			TokenValue:tokenValue,			ExpiresTime: &expiresTime,		}, &model.OAuth2Details{			User:claims.UserDetails,			Client:claims.ClientDetails,		}, nil}
 |