mirror of https://github.com/bjdgyc/anylink.git
commit
522f723b51
|
@ -107,7 +107,8 @@ func UserSet(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//修改用户资料后执行过期用户检测
|
||||||
|
sessdata.CloseUserLimittimeSession()
|
||||||
RespSucess(w, nil)
|
RespSucess(w, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package cron
|
||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/bjdgyc/anylink/sessdata"
|
||||||
"github.com/go-co-op/gocron"
|
"github.com/go-co-op/gocron"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -10,5 +11,6 @@ func Start() {
|
||||||
s := gocron.NewScheduler(time.Local)
|
s := gocron.NewScheduler(time.Local)
|
||||||
s.Cron("0 * * * *").Do(ClearAudit)
|
s.Cron("0 * * * *").Do(ClearAudit)
|
||||||
s.Cron("0 * * * *").Do(ClearStatsInfo)
|
s.Cron("0 * * * *").Do(ClearStatsInfo)
|
||||||
|
s.Every(1).Day().At("00:00").Do(sessdata.CloseUserLimittimeSession)
|
||||||
s.StartAsync()
|
s.StartAsync()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package dbdata
|
package dbdata
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/bjdgyc/anylink/base"
|
"github.com/bjdgyc/anylink/base"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
|
@ -19,6 +21,9 @@ func GetXdb() *xorm.Engine {
|
||||||
func initDb() {
|
func initDb() {
|
||||||
var err error
|
var err error
|
||||||
xdb, err = xorm.NewEngine(base.Cfg.DbType, base.Cfg.DbSource)
|
xdb, err = xorm.NewEngine(base.Cfg.DbType, base.Cfg.DbSource)
|
||||||
|
// 初始化xorm时区
|
||||||
|
xdb.DatabaseTZ = time.Local
|
||||||
|
xdb.TZLocation = time.Local
|
||||||
if err != nil {
|
if err != nil {
|
||||||
base.Fatal(err)
|
base.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,14 +29,15 @@ type User struct {
|
||||||
Nickname string `json:"nickname" xorm:"varchar(255)"`
|
Nickname string `json:"nickname" xorm:"varchar(255)"`
|
||||||
Email string `json:"email" xorm:"varchar(255)"`
|
Email string `json:"email" xorm:"varchar(255)"`
|
||||||
// Password string `json:"password"`
|
// Password string `json:"password"`
|
||||||
PinCode string `json:"pin_code" xorm:"varchar(32)"`
|
PinCode string `json:"pin_code" xorm:"varchar(32)"`
|
||||||
OtpSecret string `json:"otp_secret" xorm:"varchar(255)"`
|
LimitTime *time.Time `json:"limittime,omitempty" xorm:"Datetime limittime"` //值为null时,前端不显示
|
||||||
DisableOtp bool `json:"disable_otp" xorm:"Bool"` // 禁用otp
|
OtpSecret string `json:"otp_secret" xorm:"varchar(255)"`
|
||||||
Groups []string `json:"groups" xorm:"Text"`
|
DisableOtp bool `json:"disable_otp" xorm:"Bool"` // 禁用otp
|
||||||
Status int8 `json:"status" xorm:"Int"` // 1正常
|
Groups []string `json:"groups" xorm:"Text"`
|
||||||
SendEmail bool `json:"send_email" xorm:"Bool"`
|
Status int8 `json:"status" xorm:"Int"` // 1正常
|
||||||
CreatedAt time.Time `json:"created_at" xorm:"DateTime created"`
|
SendEmail bool `json:"send_email" xorm:"Bool"`
|
||||||
UpdatedAt time.Time `json:"updated_at" xorm:"DateTime updated"`
|
CreatedAt time.Time `json:"created_at" xorm:"DateTime created"`
|
||||||
|
UpdatedAt time.Time `json:"updated_at" xorm:"DateTime updated"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type IpMap struct {
|
type IpMap struct {
|
||||||
|
|
|
@ -104,7 +104,12 @@ func checkLocalUser(name, pwd, group string) error {
|
||||||
v := &User{}
|
v := &User{}
|
||||||
err := One("Username", name, v)
|
err := One("Username", name, v)
|
||||||
if err != nil || v.Status != 1 {
|
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) {
|
if !utils.InArrStr(v.Groups, group) {
|
||||||
|
@ -128,6 +133,21 @@ func checkLocalUser(name, pwd, group string) error {
|
||||||
return nil
|
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 (
|
var (
|
||||||
userOtpMux = sync.Mutex{}
|
userOtpMux = sync.Mutex{}
|
||||||
userOtp = map[string]time.Time{}
|
userOtp = map[string]time.Time{}
|
||||||
|
|
|
@ -4,6 +4,7 @@ go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/arl/statsviz v0.5.1
|
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-co-op/gocron v1.17.0
|
||||||
github.com/go-ldap/ldap v3.0.3+incompatible
|
github.com/go-ldap/ldap v3.0.3+incompatible
|
||||||
github.com/go-sql-driver/mysql v1.6.0
|
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.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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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/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/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=
|
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
|
return
|
||||||
}
|
}
|
||||||
index := &dbdata.SettingOther{}
|
index := &dbdata.SettingOther{}
|
||||||
dbdata.SettingGet(index)
|
if err := dbdata.SettingGet(index); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
if index.Homeindex == "" {
|
if index.Homeindex == "" {
|
||||||
index.Homeindex = "AnyLink 是一个企业级远程办公 SSL VPN 软件,可以支持多人同时在线使用。"
|
index.Homeindex = "AnyLink 是一个企业级远程办公 SSL VPN 软件,可以支持多人同时在线使用。"
|
||||||
}
|
}
|
||||||
fmt.Fprintln(w, index.Homeindex)
|
fmt.Fprintln(w, index.Homeindex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// AnyLink 是一个企业级远程办公vpn软件,可以支持多人同时在线使用。
|
// AnyLink 是一个企业级远程办公vpn软件,可以支持多人同时在线使用。
|
||||||
|
|
||||||
|
//go:build !windows
|
||||||
// +build !windows
|
// +build !windows
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"github.com/bjdgyc/anylink/base"
|
"github.com/bjdgyc/anylink/base"
|
||||||
"github.com/bjdgyc/anylink/dbdata"
|
"github.com/bjdgyc/anylink/dbdata"
|
||||||
"github.com/bjdgyc/anylink/pkg/utils"
|
"github.com/bjdgyc/anylink/pkg/utils"
|
||||||
|
mapset "github.com/deckarep/golang-set"
|
||||||
"github.com/ivpusic/grpool"
|
"github.com/ivpusic/grpool"
|
||||||
atomic2 "go.uber.org/atomic"
|
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 {
|
func GenToken() string {
|
||||||
// 生成32位的 token
|
// 生成32位的 token
|
||||||
bToken := make([]byte, 32)
|
bToken := make([]byte, 32)
|
||||||
|
|
|
@ -4,4 +4,5 @@ func Start() {
|
||||||
initIpPool()
|
initIpPool()
|
||||||
checkSession()
|
checkSession()
|
||||||
saveStatsInfo()
|
saveStatsInfo()
|
||||||
|
CloseUserLimittimeSession()
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,7 +87,8 @@
|
||||||
width="70">
|
width="70">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag v-if="scope.row.status === 1" type="success">可用</el-tag>
|
<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>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
|
@ -182,6 +183,17 @@
|
||||||
<el-input v-model="ruleForm.pin_code" placeholder="不填由系统自动生成"></el-input>
|
<el-input v-model="ruleForm.pin_code" placeholder="不填由系统自动生成"></el-input>
|
||||||
</el-form-item>
|
</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-form-item label="禁用OTP" prop="disable_otp">
|
||||||
<el-switch
|
<el-switch
|
||||||
v-model="ruleForm.disable_otp">
|
v-model="ruleForm.disable_otp">
|
||||||
|
@ -208,6 +220,7 @@
|
||||||
<el-radio-group v-model="ruleForm.status">
|
<el-radio-group v-model="ruleForm.status">
|
||||||
<el-radio :label="1" border>启用</el-radio>
|
<el-radio :label="1" border>启用</el-radio>
|
||||||
<el-radio :label="0" border>停用</el-radio>
|
<el-radio :label="0" border>停用</el-radio>
|
||||||
|
<el-radio :label="2" border>过期</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
@ -264,7 +277,6 @@ export default {
|
||||||
{required: true, message: '请输入用户邮箱', trigger: 'blur'},
|
{required: true, message: '请输入用户邮箱', trigger: 'blur'},
|
||||||
{type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change']}
|
{type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change']}
|
||||||
],
|
],
|
||||||
|
|
||||||
password: [
|
password: [
|
||||||
{min: 6, message: '长度大于 6 个字符', trigger: 'blur'}
|
{min: 6, message: '长度大于 6 个字符', trigger: 'blur'}
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in New Issue