mirror of
https://github.com/weloe/token-go.git
synced 2025-09-27 20:02:12 +08:00
207 lines
4.7 KiB
Go
207 lines
4.7 KiB
Go
package sso
|
|
|
|
import (
|
|
"errors"
|
|
"github.com/weloe/token-go/ctx"
|
|
"github.com/weloe/token-go/model"
|
|
"strings"
|
|
)
|
|
|
|
/**
|
|
=========processor SSO-Client api
|
|
*/
|
|
|
|
// SsoClientLogin SSO-Client login.
|
|
func (s *SsoEnforcer) SsoClientLogin(ctx ctx.Context) (interface{}, error) {
|
|
request := ctx.Request()
|
|
response := ctx.Response()
|
|
paramName := s.paramName
|
|
apiName := s.apiName
|
|
|
|
// get back value and redirect
|
|
back := request.Query(paramName.Back)
|
|
if back == "" {
|
|
back = "/"
|
|
}
|
|
isLogin, err := s.enforcer.IsLogin(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// if the current client is already logged in, there is no need to redirect to the SSO-Server
|
|
if isLogin {
|
|
response.Redirect(back)
|
|
return nil, nil
|
|
}
|
|
|
|
// if isLogin == false, attempt to get ticket
|
|
ticket := request.Query(paramName.Ticket)
|
|
|
|
// if ticket == "", redirect to SSO-Server, the default path is /sso/auth
|
|
if ticket == "" {
|
|
serverAuthUrl, err := s.buildServerAuthUrl(request.UrlNoQuery(), back)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
response.Redirect(serverAuthUrl)
|
|
return nil, nil
|
|
}
|
|
|
|
// else ticket != "", need to log in by ticket
|
|
var loginId string
|
|
|
|
// get current path
|
|
ssoLoginUrl := apiName.SsoLogin
|
|
if s.config.IsHttp {
|
|
// use http request to SSO-Server to check ticket in SSO-Server
|
|
var ssoLogoutCall string
|
|
if s.config.IsSlo {
|
|
// get logout callback url
|
|
if s.config.SsoLogoutCall != "" {
|
|
ssoLogoutCall = s.config.SsoLogoutCall
|
|
} else if ssoLoginUrl != "" {
|
|
ssoLogoutCall = strings.ReplaceAll(request.UrlNoQuery(), ssoLoginUrl, apiName.SsoLogoutCall)
|
|
}
|
|
}
|
|
// send http to check
|
|
checkTicketUrl, err := s.buildCheckTicketUrl(ticket, ssoLogoutCall)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// send http request
|
|
resp, err := s.request(checkTicketUrl)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if resp.Code == model.ERROR {
|
|
return nil, errors.New("request failed: " + resp.Msg)
|
|
}
|
|
loginId = resp.Data.(string)
|
|
} else {
|
|
// use adapter to check ticket
|
|
loginId, err = s.CheckTicket(ticket)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
// if set callback TicketResultHandle
|
|
if s.config.TicketResultHandle != nil {
|
|
return s.config.TicketResultHandle(loginId, back)
|
|
}
|
|
|
|
// if loginId == "", return error
|
|
if loginId == "" {
|
|
return nil, errors.New("invalid ticket: " + ticket)
|
|
}
|
|
// login in client actually
|
|
token, err := s.enforcer.Login(loginId, ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// redirect to back
|
|
response.Redirect(back)
|
|
return model.Ok().SetData(token), nil
|
|
}
|
|
|
|
// SsoClientLogout SSO-Client single-logout.
|
|
func (s *SsoEnforcer) SsoClientLogout(ctx ctx.Context) (interface{}, error) {
|
|
ssoConfig := s.config
|
|
|
|
// enable single-logout and isHttp == false
|
|
if ssoConfig.IsSlo && !ssoConfig.IsHttp {
|
|
isLogin, err := s.enforcer.IsLogin(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// check if you are logged in
|
|
if isLogin {
|
|
var id string
|
|
id, err = s.enforcer.GetLoginId(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// client logout
|
|
err = s.enforcer.LogoutById(id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// callback
|
|
return s.ssoLogoutBack(ctx)
|
|
}
|
|
|
|
}
|
|
|
|
// enable single-logout and isHttp
|
|
if ssoConfig.IsSlo && ssoConfig.IsHttp {
|
|
isLogin, err := s.enforcer.IsLogin(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !isLogin {
|
|
return s.ssoLogoutBack(ctx)
|
|
}
|
|
|
|
// get id
|
|
var id string
|
|
id, err = s.enforcer.GetLoginId(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// use SSO-Server single-logout api to logout
|
|
sloUrl, err := s.buildSloUrl(id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
res, err := s.request(sloUrl)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// check response data
|
|
if res.Code == model.SUCCESS {
|
|
login, _ := s.enforcer.IsLogin(ctx)
|
|
if login {
|
|
err := s.enforcer.Logout(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return s.ssoLogoutBack(ctx)
|
|
} else {
|
|
return nil, errors.New("request failed: " + res.Msg)
|
|
}
|
|
}
|
|
|
|
return nil, errors.New("not handle")
|
|
}
|
|
|
|
// SsoClientLogoutCall client logout callback.
|
|
func (s *SsoEnforcer) SsoClientLogoutCall(ctx ctx.Context) (interface{}, error) {
|
|
request := ctx.Request()
|
|
loginId := request.Query(s.paramName.LoginId)
|
|
if loginId == "" {
|
|
return nil, errors.New("request param must include loginId")
|
|
}
|
|
// check request param
|
|
err := s.checkRequest(request)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// logout
|
|
err = s.enforcer.LogoutById(loginId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return model.Ok().SetMsg("logout callback success"), nil
|
|
}
|
|
|
|
// GetData client build url to sent http to get data from SSO-Server.
|
|
func (s *SsoEnforcer) GetData(paramMap map[string]string) (interface{}, error) {
|
|
finalUrl, err := s.buildGetDataUrl(paramMap)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
res, err := s.config.SendHttp(finalUrl)
|
|
return res, err
|
|
}
|