# 登录回调处理 ## Handler ```go package auth import ( "fmt" "html/template" "net/http" "backend/internal/logic/auth" "backend/internal/svc" "backend/internal/types" "github.com/zeromicro/go-zero/rest/httpx" ) const callbackHTMLTemplate = ` DevOps 登录回调

DevOps 平台

Casdoor 单点登录

{{if .Success}}
登录成功!

用户信息

用户名 {{.User.Username}}
邮箱 {{.User.Email}}
用户ID {{.User.Id}}

访问令牌 (Token)

{{.Token}}
已复制到剪贴板!
{{else}}
登录失败:{{.Error}}
{{end}}
` type CallbackPageData struct { Success bool Token string User *types.UserInfo Error string } func CallbackHandler(svcCtx *svc.ServiceContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var req types.CallbackReq if err := httpx.Parse(r, &req); err != nil { renderCallbackPage(w, false, "", nil, err.Error()) return } l := auth.NewCallbackLogic(r.Context(), svcCtx) resp, err := l.Callback(&req) if err != nil { renderCallbackPage(w, false, "", nil, err.Error()) return } renderCallbackPage(w, true, resp.Token, &resp.User, "") } } func renderCallbackPage(w http.ResponseWriter, success bool, token string, user *types.UserInfo, errMsg string) { w.Header().Set("Content-Type", "text/html; charset=utf-8") data := CallbackPageData{ Success: success, Token: token, User: user, Error: errMsg, } tmpl, _ := template.New("callback").Parse(callbackHTMLTemplate) tmpl.Execute(w, data) } ``` ## Logic ```go package auth import ( "backend/internal/svc" "backend/internal/types" "backend/model" "context" "time" "github.com/casdoor/casdoor-go-sdk/casdoorsdk" "gorm.io/gorm" ) type CallbackLogic struct { ctx context.Context svcCtx *svc.ServiceContext } func NewCallbackLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CallbackLogic { return &CallbackLogic{ctx: ctx, svcCtx: svcCtx} } func (l *CallbackLogic) Callback(req *types.CallbackReq) (*types.CallbackResp, error) { // 换取 Casdoor Token authConfig, err := l.svcCtx.Casdoor.ExchangeToken(req.Code) if err != nil { return nil, err } casdoorUser := authConfig.Claims.User // 查找或创建本地用户 user, err := l.findOrCreateUser(casdoorUser) if err != nil { return nil, err } // 生成本地 JWT token, expiresAt, _ := l.svcCtx.JWT.GenerateToken(user.ID, user.Username, user.Email) return &types.CallbackResp{ Token: token, ExpiresAt: expiresAt, User: types.UserInfo{ Id: user.ID, Username: user.Username, Email: user.Email, Status: user.Status, }, }, nil } func (l *CallbackLogic) findOrCreateUser(casdoorUser *casdoorsdk.User) (*model.User, error) { var user model.User // 用用户名查询 err := l.svcCtx.DB.Where("username = ?", casdoorUser.Name).First(&user).Error if err == nil { return &user, nil } if err != gorm.ErrRecordNotFound { return nil, err } // 自动创建新用户 user = model.User{ UserType: "casdoor", Username: casdoorUser.Name, Email: casdoorUser.Email, Avatar: casdoorUser.Avatar, Role: "member", Status: 1, CreatedAt: time.Now(), } l.svcCtx.DB.Create(&user) return &user, nil } ```