mirror of https://github.com/bjdgyc/anylink.git
commit
522f723b51
|
@ -107,7 +107,8 @@ func UserSet(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
}
|
||||
|
||||
//修改用户资料后执行过期用户检测
|
||||
sessdata.CloseUserLimittimeSession()
|
||||
RespSucess(w, nil)
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package cron
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/bjdgyc/anylink/sessdata"
|
||||
"github.com/go-co-op/gocron"
|
||||
)
|
||||
|
||||
|
@ -10,5 +11,6 @@ func Start() {
|
|||
s := gocron.NewScheduler(time.Local)
|
||||
s.Cron("0 * * * *").Do(ClearAudit)
|
||||
s.Cron("0 * * * *").Do(ClearStatsInfo)
|
||||
s.Every(1).Day().At("00:00").Do(sessdata.CloseUserLimittimeSession)
|
||||
s.StartAsync()
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package dbdata
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/bjdgyc/anylink/base"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
_ "github.com/lib/pq"
|
||||
|
@ -19,6 +21,9 @@ func GetXdb() *xorm.Engine {
|
|||
func initDb() {
|
||||
var err error
|
||||
xdb, err = xorm.NewEngine(base.Cfg.DbType, base.Cfg.DbSource)
|
||||
// 初始化xorm时区
|
||||
xdb.DatabaseTZ = time.Local
|
||||
xdb.TZLocation = time.Local
|
||||
if err != nil {
|
||||
base.Fatal(err)
|
||||
}
|
||||
|
|
|
@ -29,14 +29,15 @@ type User struct {
|
|||
Nickname string `json:"nickname" xorm:"varchar(255)"`
|
||||
Email string `json:"email" xorm:"varchar(255)"`
|
||||
// Password string `json:"password"`
|
||||
PinCode string `json:"pin_code" xorm:"varchar(32)"`
|
||||
OtpSecret string `json:"otp_secret" xorm:"varchar(255)"`
|
||||
DisableOtp bool `json:"disable_otp" xorm:"Bool"` // 禁用otp
|
||||
Groups []string `json:"groups" xorm:"Text"`
|
||||
Status int8 `json:"status" xorm:"Int"` // 1正常
|
||||
SendEmail bool `json:"send_email" xorm:"Bool"`
|
||||
CreatedAt time.Time `json:"created_at" xorm:"DateTime created"`
|
||||
UpdatedAt time.Time `json:"updated_at" xorm:"DateTime updated"`
|
||||
PinCode string `json:"pin_code" xorm:"varchar(32)"`
|
||||
LimitTime *time.Time `json:"limittime,omitempty" xorm:"Datetime limittime"` //值为null时,前端不显示
|
||||
OtpSecret string `json:"otp_secret" xorm:"varchar(255)"`
|
||||
DisableOtp bool `json:"disable_otp" xorm:"Bool"` // 禁用otp
|
||||
Groups []string `json:"groups" xorm:"Text"`
|
||||
Status int8 `json:"status" xorm:"Int"` // 1正常
|
||||
SendEmail bool `json:"send_email" xorm:"Bool"`
|
||||
CreatedAt time.Time `json:"created_at" xorm:"DateTime created"`
|
||||
UpdatedAt time.Time `json:"updated_at" xorm:"DateTime updated"`
|
||||
}
|
||||
|
||||
type IpMap struct {
|
||||
|
|
|
@ -104,7 +104,12 @@ func checkLocalUser(name, pwd, group string) error {
|
|||
v := &User{}
|
||||
err := One("Username", name, v)
|
||||
if err != nil || v.Status != 1 {
|
||||
return fmt.Errorf("%s %s", name, "用户名错误")
|
||||
switch v.Status {
|
||||
case 0:
|
||||
return fmt.Errorf("%s %s", name, "用户不存在或用户已停用")
|
||||
case 2:
|
||||
return fmt.Errorf("%s %s", name, "用户已过期")
|
||||
}
|
||||
}
|
||||
// 判断用户组信息
|
||||
if !utils.InArrStr(v.Groups, group) {
|
||||
|
@ -128,6 +133,21 @@ func checkLocalUser(name, pwd, group string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// 用户过期时间到达后,更新用户状态,并返回一个状态为过期的用户切片
|
||||
func CheckUserlimittime() (limitUser []interface{}) {
|
||||
if _, err := xdb.Where("limittime <= ?", time.Now()).And("status = ?", 1).Update(&User{Status: 2}); err != nil {
|
||||
return
|
||||
}
|
||||
user := make(map[int64]User)
|
||||
if err := xdb.Where("status != ?", 1).Find(user); err != nil {
|
||||
return
|
||||
}
|
||||
for _, v := range user {
|
||||
limitUser = append(limitUser, v.Username)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
userOtpMux = sync.Mutex{}
|
||||
userOtp = map[string]time.Time{}
|
||||
|
|
|
@ -4,6 +4,7 @@ go 1.18
|
|||
|
||||
require (
|
||||
github.com/arl/statsviz v0.5.1
|
||||
github.com/deckarep/golang-set v1.8.0
|
||||
github.com/go-co-op/gocron v1.17.0
|
||||
github.com/go-ldap/ldap v3.0.3+incompatible
|
||||
github.com/go-sql-driver/mysql v1.6.0
|
||||
|
|
|
@ -98,6 +98,8 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4=
|
||||
github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=
|
||||
github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
|
|
|
@ -21,11 +21,13 @@ func LinkHome(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
index := &dbdata.SettingOther{}
|
||||
dbdata.SettingGet(index)
|
||||
if err := dbdata.SettingGet(index); err != nil {
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
if index.Homeindex == "" {
|
||||
index.Homeindex = "AnyLink 是一个企业级远程办公 SSL VPN 软件,可以支持多人同时在线使用。"
|
||||
}
|
||||
}
|
||||
fmt.Fprintln(w, index.Homeindex)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// AnyLink 是一个企业级远程办公vpn软件,可以支持多人同时在线使用。
|
||||
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package main
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/bjdgyc/anylink/base"
|
||||
"github.com/bjdgyc/anylink/dbdata"
|
||||
"github.com/bjdgyc/anylink/pkg/utils"
|
||||
mapset "github.com/deckarep/golang-set"
|
||||
"github.com/ivpusic/grpool"
|
||||
atomic2 "go.uber.org/atomic"
|
||||
)
|
||||
|
@ -113,6 +114,24 @@ func checkSession() {
|
|||
}()
|
||||
}
|
||||
|
||||
// 状态为过期的用户踢下线
|
||||
func CloseUserLimittimeSession() {
|
||||
s := mapset.NewSetFromSlice(dbdata.CheckUserlimittime())
|
||||
limitTimeToken := []string{}
|
||||
sessMux.RLock()
|
||||
for _, v := range sessions {
|
||||
v.mux.RLock()
|
||||
if v.IsActive && s.Contains(v.Username) {
|
||||
limitTimeToken = append(limitTimeToken, v.Token)
|
||||
}
|
||||
v.mux.RUnlock()
|
||||
}
|
||||
sessMux.RUnlock()
|
||||
for _, v := range limitTimeToken {
|
||||
CloseSess(v)
|
||||
}
|
||||
}
|
||||
|
||||
func GenToken() string {
|
||||
// 生成32位的 token
|
||||
bToken := make([]byte, 32)
|
||||
|
|
|
@ -4,4 +4,5 @@ func Start() {
|
|||
initIpPool()
|
||||
checkSession()
|
||||
saveStatsInfo()
|
||||
CloseUserLimittimeSession()
|
||||
}
|
||||
|
|
|
@ -87,7 +87,8 @@
|
|||
width="70">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.status === 1" type="success">可用</el-tag>
|
||||
<el-tag v-else type="danger">停用</el-tag>
|
||||
<el-tag v-if="scope.row.status === 0" type="danger">停用</el-tag>
|
||||
<el-tag v-if="scope.row.status === 2" >过期</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
|
@ -182,6 +183,17 @@
|
|||
<el-input v-model="ruleForm.pin_code" placeholder="不填由系统自动生成"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="过期时间" prop="limittime">
|
||||
<el-date-picker
|
||||
v-model="ruleForm.limittime"
|
||||
type="date"
|
||||
size="small"
|
||||
align="center"
|
||||
style="width:130px"
|
||||
placeholder="选择日期">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="禁用OTP" prop="disable_otp">
|
||||
<el-switch
|
||||
v-model="ruleForm.disable_otp">
|
||||
|
@ -208,6 +220,7 @@
|
|||
<el-radio-group v-model="ruleForm.status">
|
||||
<el-radio :label="1" border>启用</el-radio>
|
||||
<el-radio :label="0" border>停用</el-radio>
|
||||
<el-radio :label="2" border>过期</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
|
@ -264,7 +277,6 @@ export default {
|
|||
{required: true, message: '请输入用户邮箱', trigger: 'blur'},
|
||||
{type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change']}
|
||||
],
|
||||
|
||||
password: [
|
||||
{min: 6, message: '长度大于 6 个字符', trigger: 'blur'}
|
||||
],
|
||||
|
|
Loading…
Reference in New Issue