123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- package controllers
-
- import (
- "fmt"
- "net/url"
- "time"
-
- "SSO/enums"
- "SSO/models"
- "SSO/service"
- "SSO/utils"
-
- "github.com/astaxie/beego"
- )
-
- type LoginController struct {
- BaseController
- }
-
- // /login [get]
- // @param app_type:int
- // @param returnurl?:string
- // @param relogin?:bool 是否强制重新登录
- func (this *LoginController) PwdLogin() {
- token := this.Ctx.GetCookie("sso_token_cookie")
- returnURL := this.GetString("returnurl")
- appType, _ := this.GetInt("app_type")
- relogin, _ := this.GetBool("relogin", false)
- if relogin {
- token = ""
- }
-
- if url := service.GetAppURLWithAppType(appType); len(url) == 0 {
- appType = 0
- returnURL = ""
- }
- utils.TraceLog("login token: %v", token)
-
- if len(token) == 0 {
- this.Data["app_type"] = appType
- this.Data["return_url"] = returnURL
- this.TplName = "new_main/login.html"
- } else {
- if len(returnURL) == 0 {
- this.Data["app_type"] = appType
- this.Data["return_url"] = returnURL
- this.TplName = "new_main/login.html"
- } else {
- utils.TraceLog("跳过登录直接验证token")
- url := this.appendTokenParamToReturnURL(returnURL, token)
- this.Redirect(url, 302)
- }
- }
- }
-
- // /login/code [get]
- // @param app_type:int
- // @param returnurl?:string
- func (this *LoginController) CodeLogin() {
- token := this.Ctx.GetCookie("sso_token_cookie")
- returnURL := this.GetString("returnurl")
- appType, _ := this.GetInt("app_type")
-
- if url := service.GetAppURLWithAppType(appType); len(url) == 0 {
- appType = 0
- returnURL = ""
- }
- utils.TraceLog("login token: %v", token)
-
- if len(token) != 0 && len(returnURL) != 0 {
- utils.TraceLog("跳过登录直接验证token")
- url := this.appendTokenParamToReturnURL(returnURL, token)
- this.Redirect(url, 302)
-
- } else {
- redisClient := service.RedisClient()
- defer redisClient.Close()
- req := this.Ctx.Request
- addr := utils.GetIP(req)
- cur_time := time.Now().Format("2006-01-02")
- _, err := redisClient.Get("ip:host_" + cur_time + "_" + addr).Result()
- if err != nil {
- redisClient.Set("ip:host_"+cur_time+"_"+addr, 0, time.Second*24*60*60)
- }
-
- //将客户端的ip加密传给前端,作为短信验证的密钥,来验证短信发送的IP地址
- aespass := utils.AESEncrypt(addr)
- this.Data["aespass"] = aespass
-
- this.Data["app_type"] = appType
- this.Data["return_url"] = returnURL
- this.TplName = "new_main/login_by_code.html"
- }
- }
-
- // /login/submit [post]
- // @param app_type:int
- // @param mobile:string
- // @param password:string
- // @param returnurl?:string
- // 登录成功时,返回下一步跳转的链接:data.url
- func (this *LoginController) PwdLoginSubmit() {
- appType, _ := this.GetInt("app_type")
-
- utils.TraceLog("login app_type=%v", appType)
- if url := service.GetAppURLWithAppType(appType); len(url) == 0 {
- utils.TraceLog("login app_type not exist")
- appType = 0
- }
- mobile := this.GetString("mobile")
- password := this.GetString("password")
- if len(mobile) == 0 || len(password) == 0 {
- this.Data["json"] = enums.MakeFailResponseJSONWithSGJErrorCode(enums.ErrorCodeAccountOrPasswordWrong)
- this.ServeJSON()
- return
- }
- if service.IsPasswordRight(mobile, password) {
- token := utils.GenerateLoginToken(mobile)
- returnURL := this.GetString("returnurl")
- utils.TraceLog("login submit return url: %v", returnURL)
- url, err, admin := this.getRedirectURL(appType, mobile, returnURL, token)
- if err != nil {
- this.Data["json"] = enums.MakeFailResponseJSONWithSGJError(err)
- this.ServeJSON()
-
- } else {
- if admin != nil {
- this.SetSession("admin_user", admin)
- }
-
- // 保存登录令牌
- expiration, _ := beego.AppConfig.Int64("login_token_expiration_second")
- this.Ctx.SetCookie("sso_token_cookie", token, expiration, "/")
-
- redisClient := service.RedisClient()
- defer redisClient.Close()
- share_session_id := this.Ctx.Input.CruSession.SessionID()
- utils.TraceLog("share_session_id: %v", share_session_id)
- this.Ctx.SetCookie("s", share_session_id, expiration, "/", beego.AppConfig.String("cookie_rootdomain"))
- redisClient.Set(fmt.Sprintf("sso_token_%v", share_session_id), token, time.Duration(expiration)*time.Second)
-
- this.Data["json"] = enums.MakeSuccessResponseJSON(map[string]interface{}{
- "url": url,
- })
- this.ServeJSON()
- }
-
- } else {
- this.Data["json"] = enums.MakeFailResponseJSONWithSGJErrorCode(enums.ErrorCodeAccountOrPasswordWrong)
- this.ServeJSON()
- }
- }
-
- // /login/code/submit [post]
- // @param app_type:int
- // @param mobile:string
- // @param code:string
- // @param returnurl?:string
- // 登录成功时,返回下一步跳转的链接:data.url
- func (this *LoginController) CodeLoginSubmit() {
- appType, _ := this.GetInt("app_type")
- if url := service.GetAppURLWithAppType(appType); len(url) == 0 {
- appType = 0
- }
- mobile := this.GetString("mobile")
- code := this.GetString("code")
- if len(mobile) == 0 || len(code) == 0 {
- this.Data["json"] = enums.MakeFailResponseJSONWithSGJErrorCode(enums.ErrorCodeAccountOrVerCodeWrong)
- this.ServeJSON()
- return
- }
- if !service.IsMobileRegister(mobile) {
- this.Data["json"] = enums.MakeFailResponseJSONWithSGJErrorCode(enums.ErrorCodeAccountOrVerCodeWrong)
- this.ServeJSON()
- return
- }
- redisClient := service.RedisClient()
- defer redisClient.Close()
- cachedCode, err := redisClient.Get("code_msg_" + mobile).Result()
- if err != nil {
- this.Data["json"] = enums.MakeFailResponseJSONWithSGJErrorCode(enums.ErrorCodeAccountOrVerCodeWrong)
- this.ServeJSON()
- return
-
- } else {
- if code != cachedCode {
- this.Data["json"] = enums.MakeFailResponseJSONWithSGJErrorCode(enums.ErrorCodeAccountOrVerCodeWrong)
- this.ServeJSON()
- return
- } else {
- token := utils.GenerateLoginToken(mobile)
- returnURL := this.GetString("returnurl")
- url, err, admin := this.getRedirectURL(appType, mobile, returnURL, token)
- if err != nil {
- this.Data["json"] = enums.MakeFailResponseJSONWithSGJError(err)
- this.ServeJSON()
-
- } else {
- if admin != nil {
- this.SetSession("admin_user", admin)
- }
-
- // 保存登录令牌
- expiration, _ := beego.AppConfig.Int64("login_token_expiration_second")
- this.Ctx.SetCookie("sso_token_cookie", token, expiration, "/")
-
- share_session_id := this.Ctx.Input.CruSession.SessionID()
- utils.TraceLog("share_session_id: %v", share_session_id)
- this.Ctx.SetCookie("s", share_session_id, expiration, "/", beego.AppConfig.String("cookie_rootdomain"))
- redisClient.Set(fmt.Sprintf("sso_token_%v", share_session_id), token, time.Duration(expiration)*time.Second)
-
- // 清除验证码
- redisClient.Del("code_msg_" + mobile)
-
- this.Data["json"] = enums.MakeSuccessResponseJSON(map[string]interface{}{
- "url": url,
- })
- this.ServeJSON()
- }
- }
- }
- }
-
- func (this *LoginController) appendTokenParamToReturnURL(returnURL string, token string) string {
- urlStr, _ := url.QueryUnescape(returnURL)
- u, _ := url.Parse(urlStr)
- query := u.Query()
- query.Del("token")
- query.Add("token", token)
- u.RawQuery = query.Encode()
- return u.String()
- }
-
- func (this *LoginController) getRedirectURL(app_type int, mobile string, returnURL string, token string) (string, *enums.SGJError, *models.AdminUser) {
- utils.TraceLog("returnURL: %v", returnURL)
- admin := service.GetAdminUserWithMobile(mobile)
- if admin != nil {
- if admin.IsSuperAdmin { // 如果是超级管理员用户
- // 那么需要检查是否创建了机构和应用,如未创建,则前往创建
- // 如果都创建了,那么和普通管理员用户一样,需要经过其他判断得出下一步跳转的链接
- if didCreateOrg, findOrgErr := service.DidAdminUserCreateOrg(admin.Id); findOrgErr != nil {
- utils.ErrorLog("数据错误:查找mobile = %v的用户创建的机构时错误:%v", mobile, findOrgErr)
- return "", &enums.SGJError{Code: enums.ErrorCodeDataException}, nil
- } else {
- if didCreateOrg {
- if didCreateApp, findAppErr := service.DidAdminUserOrgCreateApp(admin.Id, app_type); findAppErr != nil {
- utils.ErrorLog("数据错误:查找mobile = %v的用户创建的应用时错误:%v", mobile, findOrgErr)
- return "", &enums.SGJError{Code: enums.ErrorCodeDataException}, nil
- } else {
- if !didCreateApp {
- url := this.appendTokenParamToReturnURL(beego.URLFor("OrgController.CreateApp"), token)
- return url, nil, admin
- }
- }
-
- } else {
- url := this.appendTokenParamToReturnURL(beego.URLFor("OrgController.Create"), token) // 前往创建机构的 url
- return url, nil, admin
- }
- }
- }
- if len(returnURL) != 0 {
- url := this.appendTokenParamToReturnURL(returnURL, token)
- return url, nil, admin
- }
- utils.TraceLog("login redirect url: app_type=%v", app_type)
- // 普通管理员用户
- // 如果有登录记录,则前往最近登录记录中的应用
- lastLoginLog, getLastLoginLogErr := service.GetAdminUserLastLoginLog(admin.Id, app_type)
- if getLastLoginLogErr != nil {
- utils.ErrorLog("数据错误:查找mobile = %v的用户最近一次登录记录时错误:%v", mobile, getLastLoginLogErr)
- }
- if lastLoginLog != nil {
- utils.TraceLog("%+v", lastLoginLog)
- _, getAppRoleErr := service.GetAppRole(admin.Id, lastLoginLog.OrgId, lastLoginLog.AppId)
- if getAppRoleErr != nil {
- utils.ErrorLog("数据错误:查找mobile = %v的用户的应用角色时错误:%v", mobile, getAppRoleErr)
- } else {
- url := service.GetAppURLWithAppType(int(lastLoginLog.AppType))
- if len(url) > 0 {
- return this.appendTokenParamToReturnURL(url, token), nil, admin
- }
- }
- }
- // 如果没有登录记录,则要前往其有权访问的、最高优先级的应用
- appType, getAppTypeErr := service.GetAdminUserPrioritizedAppType(admin.Id)
- if getAppTypeErr != nil {
- utils.ErrorLog("数据错误:查找mobile = %v的用户有权访问的应用的类型时错误:%v", mobile, getAppTypeErr)
- return "", &enums.SGJError{Code: enums.ErrorCodeDataException}, nil
-
- } else {
- if appType == 0 {
- utils.ErrorLog("数据错误:查找mobile = %v的用户有权访问的应用的类型时的结果错误:%v", mobile, "在超级管理员已创建应用,并且已分配角色的情况下,不可能存在查找不到相关应用")
- return "", &enums.SGJError{Code: enums.ErrorCodeDataException}, nil
- } else {
- url := this.appendTokenParamToReturnURL(service.GetAppURLWithAppType(int(appType)), token)
- return url, nil, admin
- }
- }
- } else {
- utils.ErrorLog("数据错误:查找不到mobile = %v的用户", mobile)
- return "", &enums.SGJError{Code: enums.ErrorCodeDataException}, nil
- }
- }
-
- // /logout [get]
- func (this *LoginController) Logout() {
- // 有 session.AdminUser 的话,销毁掉
- adminUserObj := this.GetSession("admin_user")
- redisClient := service.RedisClient()
- defer redisClient.Close()
- // 销毁 token
- this.Ctx.SetCookie("sso_token_cookie", "")
- redisClient.Del(fmt.Sprintf("sso_token_%v", this.Ctx.GetCookie("s")))
- if adminUserObj == nil {
- this.Redirect302(beego.URLFor("LoginController.Index"))
- return
- }
- adminUser := adminUserObj.(*models.AdminUser)
- this.DelSession("admin_user")
- redisClient.Del("sso_admin_user_info_" + adminUser.Mobile)
-
- loginLog := &models.AdminUserLoginLog{
- AdminUserId: adminUser.Id,
- OrgId: 0,
- AppId: 0,
- IP: utils.GetIP(this.Ctx.Request),
- OperateType: 2,
- AppType: 0,
- CreateTime: time.Now().Unix(),
- }
- if insertErr := service.InsertLoginLog(loginLog); insertErr != nil {
- utils.ErrorLog("为手机号为%v的用户插入一条登录记录失败:%v", adminUser.Mobile, insertErr)
- }
- // 通知其他子系统退出登录
-
- // 跳转首页
- this.Redirect302(beego.URLFor("LoginController.Index"))
- }
|