作者 唐旭辉

添加极验

#app的名称
appname = ability
#运行模式
runmode =${ProRunMode||test}
runmode =${ProRunMode||dev}
#是否自动渲染页面
autorender = false
#是否复制请求body
... ... @@ -9,6 +9,7 @@ copyrequestbody = true
#开启应用内文档
EnableDocs = false
include "dev.conf"
include "prod.conf"
include "local.conf"
... ...
... ... @@ -2,10 +2,15 @@ package controllers
import (
"encoding/json"
"fmt"
"oppmg/common/log"
"oppmg/protocol"
serveauth "oppmg/services/auth"
"oppmg/storage/redisdata"
"strconv"
"time"
"github.com/GeeTeam/gt3-golang-sdk/geetest"
)
type AuthController struct {
... ... @@ -117,15 +122,15 @@ func (c *AuthController) Me() {
companyid := c.GetCompanyId()
userinfo, err := serveauth.UserBaseInfo(userid, companyid)
if err != nil {
log.Error("%s", err)
log.Error("获取用户数据失败")
}
menus, err := serveauth.GetUserHasMenu(userid, companyid)
if err != nil {
log.Error("%s", err)
log.Error("获取用户菜单")
}
companys, err := serveauth.UserHasCompanys(userid)
if err != nil {
log.Error("%s", err)
log.Error("获取用户的公司")
}
data := map[string]interface{}{
"user": userinfo,
... ... @@ -135,3 +140,53 @@ func (c *AuthController) Me() {
msg = protocol.NewReturnResponse(data, nil)
return
}
const (
captchaID = "48a6ebac4ebc6642d68c217fca33eb4d"
privateKey = "4f1c085290bec5afdc54df73535fc361"
)
func (c *AuthController) RegisterGeetest() {
geetest := geetest.NewGeetestLib(captchaID, privateKey, 2*time.Second)
status, responseBt := geetest.PreProcess("", "")
c.SetSession("geetest_status", status)
c.Ctx.Output.Body(responseBt)
return
}
func (c *AuthController) ValidateGeetest() {
type Parameter struct {
GeetestChallenge string `form:"geetest_challenge"`
GeetestValidate string `form:"geetest_validate"`
GeetestSeccode string `form:"geetest_seccode"`
}
var (
param Parameter
geetestRes bool
status int
)
err := c.ParseForm(&param)
if err != nil {
log.Error("解析表单数据失败;%s", err)
}
val := c.GetSession("geetest_status")
status, _ = strconv.Atoi(fmt.Sprint(val))
geetest := geetest.NewGeetestLib(captchaID, privateKey, 2*time.Second)
if status == 1 {
geetestRes = geetest.SuccessValidate(param.GeetestChallenge, param.GeetestValidate, param.GeetestSeccode, "", "")
} else {
geetestRes = geetest.FailbackValidate(param.GeetestChallenge, param.GeetestValidate, param.GeetestSeccode)
}
res := make(map[string]interface{})
if geetestRes {
res["code"] = 0
res["msg"] = "Success"
} else {
res["code"] = -100
res["msg"] = "Failed"
}
responseBt, _ := json.Marshal(res)
c.Ctx.Output.Body(responseBt)
return
}
... ...
... ... @@ -20,14 +20,14 @@ type BaseController struct {
//Prepare 实现beego.ControllerInterface 的接口
func (this *BaseController) Prepare() {
this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Headers", "*")
if this.Ctx.Input.Method() == "OPTIONS" {
this.Ctx.ResponseWriter.WriteHeader(204)
this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
//this.Ctx.WriteString("")
return
}
// this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Origin", "*")
// this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Headers", "*")
// if this.Ctx.Input.Method() == "OPTIONS" {
// this.Ctx.ResponseWriter.WriteHeader(204)
// this.Ctx.ResponseWriter.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
// //this.Ctx.WriteString("")
// return
// }
p := this.Ctx.Input.GetData("RouterPattern")
fmt.Println("====>r:", p)
}
... ...
... ... @@ -415,7 +415,6 @@ func (c *CompanyController) InitCompany() {
} else {
err = protocol.NewErrWithMessage("1")
}
msg = protocol.NewReturnResponse(nil, err)
return
}
... ... @@ -440,6 +439,42 @@ func (c *CompanyController) GetCompanyForUCenter() {
return
}
//获取用户详情
//@router /user/info
func (c *CompanyController) UserDetail() {
var msg *protocol.ResponseMessage
defer func() {
c.ResposeJson(msg)
}()
type Parameter struct {
UserCompanyId int64 `json:"user_company_id"`
}
var param Parameter
if err := json.Unmarshal(c.Ctx.Input.RequestBody, &param); err != nil {
log.Error("json 解析失败 err:%s", err)
msg = protocol.BadRequestParam("1")
return
}
userdata, _ := servecompany.GetUserData(param.UserCompanyId)
departs := servecompany.GetUserDepartment(param.UserCompanyId)
positions := servecompany.GetUserPosition(param.UserCompanyId)
roles := servecompany.GetUserRole(param.UserCompanyId)
type ResponseUserDetail struct {
protocol.UserInfoBase
Departs []protocol.DepartmentBase `json:"departs"`
Positions []protocol.PositionBase `json:"positions"`
Roles []protocol.RoleBase `json:"roles"`
}
data := ResponseUserDetail{
UserInfoBase: userdata,
Departs: departs,
Positions: positions,
Roles: roles,
}
msg = protocol.NewReturnResponse(data, nil)
return
}
//DepartmentUser 获取部门下成员
//@router /department/user [post]
func (c *CompanyController) DepartmentUser() {
... ... @@ -489,15 +524,6 @@ func (c *CompanyController) CurrentCompanyInfo() {
defer func() {
c.ResposeJson(msg)
}()
// type Parameter struct {
// Logo string `json:"string"`
// }
// var param Parameter
// if err := json.Unmarshal(c.Ctx.Input.RequestBody, &param); err != nil {
// log.Error("json 解析失败 err:%s", err)
// msg = protocol.BadRequestParam("1")
// return
// }
companyid := c.GetCompanyId()
companybase, err := servecompany.CompanyBaseInfo(companyid)
msg = protocol.NewReturnResponse(companybase, err)
... ...
... ... @@ -4,6 +4,7 @@ go 1.13
require (
github.com/360EntSecGroup-Skylar/excelize/v2 v2.0.2
github.com/GeeTeam/gt3-golang-sdk v0.0.0-20190704102600-e89c6d964c8f
github.com/astaxie/beego v1.11.1
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/go-redis/redis v6.15.6+incompatible
... ...
github.com/360EntSecGroup-Skylar/excelize/v2 v2.0.2 h1:StMrA6UQ5Cm6206DxXGuV/NMqSIOIDoMXMYt8JPe1lE=
github.com/360EntSecGroup-Skylar/excelize/v2 v2.0.2/go.mod h1:EfRHD2k+Kd7ijnqlwOrH1IifwgWB9yYJ0pdXtBZmlpU=
github.com/GeeTeam/gt3-golang-sdk v0.0.0-20190704102600-e89c6d964c8f h1:FpIAcTBZpoM5uD2+zKbTyT+6Oz0efWw4ZWnr8FtdQ+g=
github.com/GeeTeam/gt3-golang-sdk v0.0.0-20190704102600-e89c6d964c8f/go.mod h1:vqCh/LExdPmL5SULXE/9DHbuE4t3iLkzRYoNGxEvg/o=
github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/astaxie/beego v1.11.1 h1:6DESefxW5oMcRLFRKi53/6exzup/IR6N4EzzS1n6CnQ=
github.com/astaxie/beego v1.11.1/go.mod h1:i69hVzgauOPSw5qeyF4GVZhn7Od0yG5bbCGzmhbWxgQ=
... ...
... ... @@ -12,6 +12,10 @@ import (
_ "github.com/go-sql-driver/mysql"
)
func init() {
beego.BConfig.WebConfig.Session.SessionOn = true
}
func main() {
common.ResetCommonConfig()
log.Debug("加载配置%s", config.MConfig.ConfigName)
... ...
... ... @@ -91,7 +91,7 @@ var AllowOption = func(ctx *context.Context) {
AllowHeaders: []string{"Origin", "Accept", "Content-Type", "Authorization",
"x-mmm-cid", "x-mmm-uid", "x-mmm-accesstoken", "x-mmm-refreshtoken", "x-requested-with"}, //允许的头部信息
ExposeHeaders: []string{"Content-Length"}, //允许暴露的头信息
AllowCredentials: false, //不允许共享AuthTuffic证书
AllowCredentials: true, //不允许共享AuthTuffic证书
AllowAllOrigins: true, //允许的请求来源
})
f(ctx)
... ...
... ... @@ -90,7 +90,7 @@ type Template struct {
Code string `json:"code" valid:"Required; MaxSize(6)"`
ChanceTypeId int `json:"chanceTypeId" valid:"Required;"` //机会类型编号
Name string `json:"name" valid:"Required;"`
Doc string `json:"doc" valid:"Required;"`
Doc string `json:"doc"`
Icon string `json:"icon" valid:"Required;"`
InputList []*InputElement `json:"inputList" valid:"Required;"`
}
... ...
... ... @@ -51,3 +51,9 @@ type DepartAndUser struct {
Departments []DepartmentBase `json:"departments"`
Members []DepartmentMember `json:"members"`
}
type UserInfoBase struct {
UserCompanyId int64 `json:"user_company_id"`
Name string `json:"name"`
Phone string `json:"phone"`
}
... ...
... ... @@ -123,9 +123,9 @@ type ResponseCompanyBase struct {
//CenterCompanyInfo 统一用户中心调用的公司数据
type CenterCompanyInfo struct {
CompanyId int64 `json:"company_id"` //总后台的公司id
CompanyName string `json:"company_name"` //
AdminId int64 `json:"admin_id"` //统一用户中心的用户id
CompanyId int64 `json:"company_id"` //总后台的公司id
CompanyName string `json:"company_name"` //
// AdminId int64 `json:"admin_id"` //统一用户中心的用户id
AdminAccount string `json:"admin_account"`
AdminName string `json:"admin_name"`
Status int8 `json:"status"` //公司的状态 【1:启用】【2:禁用】
... ...
... ... @@ -46,6 +46,7 @@ func init() {
beego.NSRouter("/edit", &controllers.CompanyController{}, "post:UserEdit"),
beego.NSRouter("/delete", &controllers.CompanyController{}, "post:UserDelete"),
beego.NSRouter("/allow_forbid", &controllers.CompanyController{}, "post:UserAllowForbid"),
beego.NSRouter("/info", &controllers.CompanyController{}, "post:UserDetail"),
),
beego.NSNamespace("/auth",
beego.NSRouter("/change_company", &controllers.AuthController{}, "post:ChangeCompany"),
... ... @@ -89,6 +90,8 @@ func init() {
beego.NSBefore(middleware.AllowOption),
beego.NSBefore(middleware.LogRequestData),
beego.NSRouter("/login", &controllers.AuthController{}, "post:Login"),
beego.NSRouter("/startCaptcha", &controllers.AuthController{}, "post:RegisterGeetest"),
beego.NSRouter("/verifyCaptcha", &controllers.AuthController{}, "post:ValidateGeetest"),
)
nsUcenter := beego.NewNamespace("/ucenter",
beego.NSBefore(middleware.LogRequestData),
... ...
package company
import (
"fmt"
"oppmg/common/log"
"oppmg/models"
"oppmg/protocol"
"oppmg/services/ucenter"
"time"
"github.com/astaxie/beego/orm"
)
// type CenterCompanyInfo struct {
// CompanyId int64
// CompanyName string
// AdminId int64
// AdminAccount string
// AdminName string
// }
// func GetCenterCompanyInfo(companyid int64) (CenterCompanyInfo, error) {
// //TODO 调用统一用户中心的数据
// data := CenterCompanyInfo{
// CompanyId: 9999 + companyid,
// CompanyName: "调试用公司数据",
// AdminId: 9999 + companyid,
// AdminAccount: "调试用自己修改",
// AdminName: "调试用自己修改",
// }
// return data, nil
// }
//InitCompanyInfo 初始化公司
//@uCompanyid 从统一用户中心获取的公司id companyid,
func InitCompanyInfo(centerCompany protocol.CenterCompanyInfo) error {
// var (
// centerCompany CenterCompanyInfo
... ... @@ -159,7 +137,7 @@ func initAdminUser(centerCompany protocol.CenterCompanyInfo, o orm.Ormer) (*mode
newUser = &models.User{}
)
err = o.QueryTable(&models.User{}).
Filter("user_center_id", centerCompany.AdminId).
Filter("phone", centerCompany.AdminAccount).
Filter("delete_at", 0).
One(newUser)
if err == nil {
... ... @@ -177,16 +155,21 @@ func initAdminUser(centerCompany protocol.CenterCompanyInfo, o orm.Ormer) (*mode
return nil, err
}
} else if err == orm.ErrNoRows {
ucenterUser, err := ucenter.RequestUCenterAddUser(centerCompany.AdminAccount, centerCompany.AdminName, "")
if err != nil {
log.Error("获取统一用户中心数据失败 :%s", err)
}
//添加用户
newUser = &models.User{
Phone: centerCompany.AdminAccount,
UserCenterId: centerCompany.AdminId,
NickName: centerCompany.AdminName,
Icon: ucenterUser.Data.Avatar,
Accid: ucenterUser.Data.Accid,
UserCenterId: ucenterUser.Data.Id,
CsAccount: ucenterUser.Data.CustomerAccount,
}
id, err := models.AddUser(newUser, o)
fmt.Println("-=====>user_id=", id)
_, err = models.AddUser(newUser, o)
if err != nil {
log.Error("添加用户数据失败:%s", err)
return nil, err
}
... ...
... ... @@ -614,6 +614,30 @@ func GetUserRole(usercompanyid int64) []protocol.RoleBase {
return data
}
func GetUserData(usercompanyid int64) (protocol.UserInfoBase, error) {
var (
ucompany *models.UserCompany
err error
uinfo protocol.UserInfoBase
)
ucompany, err = models.GetUserCompanyById(usercompanyid)
if err != nil {
log.Error("获取GetUserCompanyById失败 :%s", err)
return uinfo, err
}
userdata, err := models.GetUserById(ucompany.UserId)
if err != nil {
log.Error("获取GetUserById 失败:%s", err)
return uinfo, err
}
uinfo = protocol.UserInfoBase{
UserCompanyId: ucompany.Id,
Name: ucompany.NickName,
Phone: userdata.Phone,
}
return uinfo, nil
}
//禁用用户
func UserForbid(userCompanyids []int64, companyid int64) error {
if len(userCompanyids) == 0 {
... ...
package geetest
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"errors"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
)
type GeetestLib struct {
CaptchaID string
PrivateKey string
Client *http.Client
}
type FailbackRegisterRespnse struct {
Success int `json:"success"`
GT string `json:"gt"`
Challenge string `json:"challenge"`
NewCaptcha int `json:"new_captcha"`
}
const (
geetestHost = "http://api.geetest.com"
registerURL = geetestHost + "/register.php"
validateURL = geetestHost + "/validate.php"
)
func MD5Encode(input string) string {
md5Instant := md5.New()
md5Instant.Write([]byte(input))
return hex.EncodeToString(md5Instant.Sum(nil))
}
// 初始化 GeetestLib
func NewGeetestLib(capthcaID string, privateKey string, timeOut time.Duration) (geetest GeetestLib){
client := &http.Client{Timeout: timeOut}
geetest = GeetestLib{capthcaID, privateKey, client}
return
}
func (g *GeetestLib) getFailBackRegisterResponse(success int, challenge string) []byte {
if challenge == "" {
challenge = hex.EncodeToString(md5.New().Sum(nil))
}
response := FailbackRegisterRespnse{
success,
g.CaptchaID,
challenge,
1,
}
res, _ := json.Marshal(response)
return res
}
func (g *GeetestLib) do(req *http.Request) (body []byte, err error) {
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
var resp *http.Response
if resp, err = g.Client.Do(req); err != nil {
return
}
defer resp.Body.Close()
if resp.StatusCode >= http.StatusInternalServerError {
err = errors.New("http status code 5xx")
return
}
if body, err = ioutil.ReadAll(resp.Body); err != nil {
return
}
return
}
func (g *GeetestLib) PreProcess(userID string, userIP string) (int8, []byte) {
params := url.Values{}
params.Add("gt", g.CaptchaID)
params.Add("new_captcha", "1")
if userID != "" {
params.Add("user_id", userID)
}
if userIP != "" {
params.Add("ip_adress", userIP)
}
req, _ := http.NewRequest("GET", registerURL+"?"+params.Encode(), nil)
body, err := g.do(req)
if err != nil {
return 0, g.getFailBackRegisterResponse(0, "")
}
challenge := string(body)
if len(challenge) != 32 {
return 0, g.getFailBackRegisterResponse(0, "")
} else {
challenge = MD5Encode(challenge + g.PrivateKey)
return 1, g.getFailBackRegisterResponse(1, challenge)
}
}
func (g *GeetestLib) checkParas(challenge string, validate string, seccode string) bool {
if challenge == "" || validate == "" || seccode == "" {
return false
}
return true
}
func (g *GeetestLib) checkSuccessRes(challenge string, validate string) bool {
return MD5Encode(g.PrivateKey+"geetest"+challenge) == validate
}
func (g *GeetestLib) checkFailbackRes(challenge string, validate string) bool {
return MD5Encode(challenge) == validate
}
func (g *GeetestLib) SuccessValidate(challenge string, validate string, seccode string, userID string, userIP string) bool {
if !g.checkParas(challenge, validate, seccode) {
return false
}
if !g.checkSuccessRes(challenge, validate) {
return false
}
params := url.Values{}
params.Add("seccode", seccode)
params.Add("challenge", challenge)
params.Add("captchaid", g.CaptchaID)
params.Add("sdk", "golang_v1.0.0")
if userID != "" {
params.Add("user_id", userID)
}
if userIP != "" {
params.Add("ip_adress", userIP)
}
req, _ := http.NewRequest("POST", validateURL, strings.NewReader(params.Encode()))
body, err := g.do(req)
if err != nil {
return false
}
res := string(body)
return res == MD5Encode(seccode)
}
func (g *GeetestLib) FailbackValidate(challenge string, validate string, seccode string) bool {
if !g.checkParas(challenge, validate, seccode) {
return false
}
if !g.checkFailbackRes(challenge, validate) {
return false
}
return true
}
... ...
# github.com/360EntSecGroup-Skylar/excelize/v2 v2.0.2
github.com/360EntSecGroup-Skylar/excelize/v2
# github.com/GeeTeam/gt3-golang-sdk v0.0.0-20190704102600-e89c6d964c8f
github.com/GeeTeam/gt3-golang-sdk/geetest
# github.com/astaxie/beego v1.11.1
github.com/astaxie/beego
github.com/astaxie/beego/config
... ...