Example #1
0
// 获取微信认证页面的 url
//  需要提供 redirect_uri
func AuthURLHandler(ctx *gin.Context) {
	// MustAuthHandler(ctx)
	queryValues := ctx.Request.URL.Query()
	redirectURI := queryValues.Get("redirect_uri")
	if redirectURI == "" {
		ctx.JSON(200, errors.ErrBadRequest)
		return
	}
	if !strings.HasPrefix(redirectURI, "https:") && !strings.HasPrefix(redirectURI, "http:") {
		redirectURI = config.ConfigData.WebServer.BaseURL + redirectURI
	}

	tk := ctx.MustGet("sso_token").(*token.Token)
	ss := ctx.MustGet("sso_session").(*session.Session)

	ss.OAuth2State = string(random.NewRandomEx())
	if err := session.Set(tk.SessionId, ss); err != nil {
		glog.Errorln(err)
		ctx.JSON(200, errors.ErrInternalServerError)
		return
	}

	authURL := oauth2.AuthCodeURL(config.ConfigData.Weixin.MP.AppId, redirectURI, "snsapi_userinfo", ss.OAuth2State, nil)

	resp := struct {
		*errors.Error
		URL string `json:"url"`
	}{
		Error: errors.ErrOK,
		URL:   authURL,
	}
	ctx.JSON(200, &resp)
	return
}
Example #2
0
// 获取请求用户授权的参数(appid, state, scope)
func AuthParaHandler(ctx *gin.Context) {
	// MustAuthHandler(ctx)
	tk := ctx.MustGet("sso_token").(*token.Token)
	ss := ctx.MustGet("sso_session").(*session.Session)

	ss.OAuth2State = string(random.NewRandomEx())
	if err := session.Set(tk.SessionId, ss); err != nil {
		glog.Errorln(err)
		ctx.JSON(200, errors.ErrInternalServerError)
		return
	}

	resp := struct {
		*errors.Error
		AppId string `json:"appid"`
		State string `json:"state"`
		Scope string `json:"scope"`
	}{
		Error: errors.ErrOK,
		AppId: config.ConfigData.Weixin.Open.App.AppId,
		State: ss.OAuth2State,
		Scope: "snsapi_userinfo",
	}
	ctx.JSON(200, &resp)
	return
}
Example #3
0
// 申请发送一个校验码到邮箱.
//  uri?email=XXX
func RequestForEmailHandler(ctx *gin.Context) {
	// MustAuthHandler(ctx)
	queryValues := ctx.Request.URL.Query()
	email := queryValues.Get("email")
	if email == "" {
		ctx.JSON(200, errors.ErrBadRequest)
		return
	}
	if !check.IsMailString(email) {
		ctx.JSON(200, errors.ErrBadRequest)
		return
	}

	tk := ctx.MustGet("sso_token").(*token.Token)
	ss := ctx.MustGet("sso_session").(*session.Session)

	code := generateCode()
	checkcode := session.CheckCode{
		Key:   email,
		Code:  code,
		Times: 0,
	}
	ss.EmailCheckCode = &checkcode
	if err := session.Set(tk.SessionId, ss); err != nil {
		glog.Errorln(err)
		ctx.JSON(200, errors.ErrInternalServerError)
		return
	}

	if err := sendCodeToEmail(email, code); err != nil {
		glog.Errorln(err)
		ctx.JSON(200, errors.ErrInternalServerError)
		return
	}

	ctx.JSON(200, errors.ErrOK)
	return
}
Example #4
0
// 申请发送一个校验码到手机.
//  uri?phone=XXX
func RequestForPhoneHandler(ctx *gin.Context) {
	// MustAuthHandler(ctx)
	queryValues := ctx.Request.URL.Query()
	phone := queryValues.Get("phone")
	if phone == "" {
		ctx.JSON(200, errors.ErrBadRequest)
		return
	}
	if !check.IsChinaMobileString(phone) {
		ctx.JSON(200, errors.ErrBadRequest)
		return
	}

	tk := ctx.MustGet("sso_token").(*token.Token)
	ss := ctx.MustGet("sso_session").(*session.Session)

	code := generateCode()
	checkcode := session.CheckCode{
		Key:   phone,
		Code:  code,
		Times: 0,
	}
	ss.PhoneCheckCode = &checkcode
	if err := session.Set(tk.SessionId, ss); err != nil {
		glog.Errorln(err)
		ctx.JSON(200, errors.ErrInternalServerError)
		return
	}

	if err := sendCodeToPhone(phone, code); err != nil {
		glog.Errorln(err)
		ctx.JSON(200, errors.ErrInternalServerError)
		return
	}

	ctx.JSON(200, errors.ErrOK)
	return
}
Example #5
0
// 刷新 token
func RefreshHandler(ctx *gin.Context) {
	tkString := ctx.Request.Header.Get("x-token")
	if tkString == "" {
		ctx.JSON(200, errors.ErrTokenMissing)
		return
	}

	// 解析 token
	tk := &token.Token{}
	if err := tk.Decode([]byte(tkString)); err != nil {
		glog.Errorln(err)
		ctx.JSON(200, errors.ErrTokenDecodeFailed)
		return
	}

	// 如果是 guest 直接返回
	if tk.AuthType == token.AuthTypeGuest {
		resp := struct {
			*errors.Error
			Token string `json:"token"`
		}{
			Error: errors.ErrOK,
			Token: tkString,
		}
		ctx.JSON(200, &resp)
		return
	}

	timestamp := time.Now().Unix()
	if timestamp >= tk.ExpirationRefresh {
		ctx.JSON(200, errors.ErrTokenRefreshExpired)
		return
	}
	if timestamp+1200 < tk.ExpirationAccess { // 过早的刷新也是直接返回
		resp := struct {
			*errors.Error
			Token string `json:"token"`
		}{
			Error: errors.ErrOK,
			Token: tkString,
		}
		ctx.JSON(200, &resp)
		return
	}
	if tk.ExpirationAccess >= tk.ExpirationRefresh { // 提前 1200秒 暴力的结束, 防止客户端循环的刷新
		ctx.JSON(200, errors.ErrTokenRefreshExpired)
		return
	}

	// 现在我们真的需要刷新token啦!!!

	// 获取 Session 并判断与 token 是否匹配
	ss, err := session.Get(tk.SessionId)
	if err != nil {
		glog.Errorln(err)
		if err == errors.ErrNotFound {
			ctx.JSON(200, errors.ErrTokenInvalid)
			return
		}
		ctx.JSON(200, errors.ErrInternalServerError)
		return
	}
	if !security.SecureCompareString(tk.Signatrue, ss.TokenSignature) {
		ctx.JSON(200, errors.ErrTokenInvalid)
		return
	}

	// 获取用户信息并判断与 token, session 是否一致
	user, err := model.Get(ss.UserId)
	if err != nil {
		glog.Errorln(err)
		if err == model.ErrNotFound {
			ctx.JSON(200, errors.ErrTokenInvalid)
			return
		}
		ctx.JSON(200, errors.ErrInternalServerError)
		return
	}
	bindType, err := token.GetBindType(tk.AuthType)
	if err != nil {
		glog.Errorln(err)
		ctx.JSON(200, errors.ErrTokenInvalid)
		return
	}
	if user.BindTypes&bindType == 0 {
		ctx.JSON(200, errors.ErrTokenInvalid)
		return
	}
	if tk.AuthType == token.AuthTypeEmailPassword || tk.AuthType == token.AuthTypePhonePassword {
		if ss.PasswordTag != user.PasswordTag {
			ctx.JSON(200, errors.ErrTokenInvalid)
			return
		}
	}

	tk2 := token.Token{
		SessionId:         tk.SessionId,
		TokenId:           token.NewTokenId(),
		AuthType:          tk.AuthType,
		ExpirationAccess:  token.ExpirationAccess(timestamp),
		ExpirationRefresh: tk.ExpirationRefresh,
	}
	if tk2.ExpirationAccess > tk2.ExpirationRefresh {
		tk2.ExpirationAccess = tk2.ExpirationRefresh
	}
	tk2EncodedBytes, err := tk2.Encode()
	if err != nil {
		glog.Errorln(err)
		ctx.JSON(200, errors.ErrTokenEncodeFailed)
		return
	}

	ss.TokenSignature = tk2.Signatrue
	if err = session.Set(tk2.SessionId, ss); err != nil {
		glog.Errorln(err)
		ctx.JSON(200, errors.ErrInternalServerError)
		return
	}

	resp := struct {
		*errors.Error
		Token string `json:"token"`
	}{
		Error: errors.ErrOK,
		Token: string(tk2EncodedBytes),
	}
	ctx.JSON(200, &resp)
	return
}