package controllers
import (
"crypto/rand"
"database/sql"
"encoding/base64"
"encoding/json"
"fmt"
"github.com/astaxie/beego"
"github.com/astaxie/beego/session"
"io/ioutil"
"net/http"
"net/url"
"time"
"your_project_name/models"
)
type LoginController struct {
beego.Controller
}
var db *sql.DB
var globalSessions *session.Manager
func init() {
// 创建 MySQL 数据库连接
var err error
db, err = sql.Open("mysql", "username:password@tcp(localhost:3306)/database")
if err != nil {
panic("Failed to connect to database")
}
defer db.Close()
// 初始化 Beego 框架的会话管理器
beego.BConfig.WebConfig.Session.SessionOn = true
globalSessions, _ = session.NewManager("memory", &session.ManagerConfig{
CookieName: "session_name",
Gclifetime: 3600,
EnableSetCookie: true,
Secure: false,
CookieLifeTime: 3600,
})
go globalSessions.GC()
}
func (c *LoginController) Get() {
state := generateRandomString(16)
c.SetSession("state", state)
authURL := fmt.Sprintf("https://open.weixin.qq.com/connect/qrconnect?appid=YOUR_APP_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=code&scope=snsapi_login&state=%s#wechat_redirect", state)
c.Redirect(authURL, http.StatusTemporaryRedirect)
}
func (c *LoginController) Callback() {
code := c.GetString("code")
state := c.GetString("state")
session, _ := globalSessions.SessionStart(c.Ctx.ResponseWriter, c.Ctx.Request)
defer session.SessionRelease(c.Ctx.ResponseWriter)
if state != session.Get("state") {
c.Data["json"] = map[string]interface{}{"message": "Invalid state parameter"}
c.ServeJSON()
return
}
accessTokenResp, err := getAccessToken(code)
if err != nil {
c.Data["json"] = map[string]interface{}{"message": "Failed to get access token"}
c.ServeJSON()
return
}
userInfo, err := getUserInfo(accessTokenResp.AccessToken, accessTokenResp.OpenID)
if err != nil {
c.Data["json"] = map[string]interface{}{"message": "Failed to get user information"}
c.ServeJSON()
return
}
user, err := models.GetUserByOpenIDOrUnionID(userInfo.OpenID, userInfo.UnionID)
if err != nil {
// 用户未注册,保存用户信息到数据库
user = &models.User{
OpenID: userInfo.OpenID,
UnionID: userInfo.UnionID,
HeadImg: userInfo.HeadImg,
}
err = user.Save()
if err != nil {
// 处理错误
}
} else {
// 用户已注册,从数据库获取用户信息
err = user.LoadInfo()
if err != nil {
// 处理错误
}
}
session.Set("user", user)
session.Save()
c.Data["json"] = map[string]interface{}{"message": "Login successful", "user": user}
c.ServeJSON()
}
func generateRandomString(n int) string {
b := make([]byte, n)
_, err := rand.Read(b)
if err != nil {
return ""
}
return base64.URLEncoding.EncodeToString(b)
}
func getAccessToken(code string) (*models.AccessTokenResponse, error) {
apiURL := "https://api.weixin.qq.com/sns/oauth2/access_token"
values := url.Values{}
values.Set("appid", "YOUR_APP_ID")
values.Set("secret", "YOUR_APP_SECRET")
values.Set("code", code)
values.Set("grant_type", "authorization_code")
resp, err := http.Get(apiURL + "?" + values.Encode())
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var accessTokenResp models.AccessTokenResponse
err = json.Unmarshal(body, &accessTokenResp)
if err != nil {
return nil, err
}
return &accessTokenResp, nil
}
func getUserInfo(accessToken, openid string) (*models.UserInfo, error) {
apiURL := fmt.Sprintf("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s", accessToken, openid)
resp, err := http.Get(apiURL)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var userInfoResp models.UserInfoResponse
err = json.Unmarshal(body, &userInfoResp)
if err != nil {
return nil, err
}
userInfo := &models.UserInfo{
OpenID: userInfoResp.OpenID,
UnionID: userInfoResp.UnionID,
HeadImg: userInfoResp.AvatarURL,
}
return userInfo, nil
}
复制