批量更新
This commit is contained in:
@@ -0,0 +1,125 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"server/models"
|
||||
authsvc "server/services/auth"
|
||||
|
||||
beego "github.com/beego/beego/v2/server/web"
|
||||
)
|
||||
|
||||
// AuthSessionController 会话管理(用户自助:查看在线设备、踢下线)
|
||||
type AuthSessionController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
func (c *AuthSessionController) serveJSON(data map[string]interface{}) {
|
||||
c.Data["json"] = data
|
||||
_ = c.ServeJSON()
|
||||
}
|
||||
|
||||
// DevicesPage 在线设备页(浏览器访问,依赖认证中心会话 Cookie)
|
||||
// GET /auth/devices
|
||||
func (c *AuthSessionController) DevicesPage() {
|
||||
sid := strings.TrimSpace(c.Ctx.GetCookie(sessionCookieName))
|
||||
if sid == "" {
|
||||
c.Redirect("/auth/login", 302)
|
||||
return
|
||||
}
|
||||
session, err := authsvc.GetSession(sid)
|
||||
if err != nil {
|
||||
c.Redirect("/auth/login", 302)
|
||||
return
|
||||
}
|
||||
|
||||
list, err := authsvc.ListActiveSessions(session.IdentityID)
|
||||
if err != nil {
|
||||
list = nil
|
||||
}
|
||||
|
||||
items := make([]map[string]interface{}, 0, len(list))
|
||||
now := time.Now()
|
||||
for _, s := range list {
|
||||
device := "未知设备"
|
||||
if s.DeviceName != nil && strings.TrimSpace(*s.DeviceName) != "" {
|
||||
device = *s.DeviceName
|
||||
}
|
||||
ip := "-"
|
||||
if s.IP != nil {
|
||||
ip = *s.IP
|
||||
}
|
||||
client := s.ClientID
|
||||
if client == "" {
|
||||
client = "-"
|
||||
}
|
||||
items = append(items, map[string]interface{}{
|
||||
"Sid": s.Sid,
|
||||
"Current": s.Sid == sid,
|
||||
"Device": device,
|
||||
"IP": ip,
|
||||
"Client": client,
|
||||
"LoginAt": s.LoginAt.Format("2006-01-02 15:04"),
|
||||
"LastAt": s.LastAccessAt.Format("2006-01-02 15:04"),
|
||||
"Expired": s.ExpiresAt.Before(now),
|
||||
"Tid": s.Tid,
|
||||
})
|
||||
}
|
||||
|
||||
c.Data["Sessions"] = items
|
||||
c.Data["Success"] = c.GetString("success")
|
||||
c.Data["Error"] = c.GetString("error")
|
||||
c.TplName = "auth/devices.tpl"
|
||||
}
|
||||
|
||||
// KickPage 踢下线指定设备(页面入口,踢完后回到设备页)
|
||||
// GET /auth/devices/kick?sid=
|
||||
func (c *AuthSessionController) KickPage() {
|
||||
target := strings.TrimSpace(c.GetString("sid"))
|
||||
current := strings.TrimSpace(c.Ctx.GetCookie(sessionCookieName))
|
||||
if current == "" {
|
||||
c.Redirect("/auth/login", 302)
|
||||
return
|
||||
}
|
||||
session, err := authsvc.GetSession(current)
|
||||
if err != nil {
|
||||
c.Redirect("/auth/login", 302)
|
||||
return
|
||||
}
|
||||
if target == "" {
|
||||
c.Redirect("/auth/devices?error="+url.QueryEscape("参数错误"), 302)
|
||||
return
|
||||
}
|
||||
|
||||
// 只允许操作自己名下的会话
|
||||
owned := false
|
||||
if list, e := authsvc.ListActiveSessions(session.IdentityID); e == nil {
|
||||
for _, s := range list {
|
||||
if s.Sid == target {
|
||||
owned = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !owned {
|
||||
c.Redirect("/auth/devices?error="+url.QueryEscape("无权操作该设备"), 302)
|
||||
return
|
||||
}
|
||||
if target == current {
|
||||
c.Redirect("/auth/devices?error="+url.QueryEscape("不能踢掉当前设备,请直接登出"), 302)
|
||||
return
|
||||
}
|
||||
|
||||
if err := authsvc.RevokeSession(target, models.RevokeReasonAdmin); err != nil {
|
||||
c.Redirect("/auth/devices?error="+url.QueryEscape("操作失败"), 302)
|
||||
return
|
||||
}
|
||||
// 同步吊销该会话的刷新令牌,确保对方无法续期
|
||||
_, _ = models.Orm.QueryTable(new(models.AuthRefreshToken)).
|
||||
Filter("sid", target).
|
||||
Update(map[string]interface{}{"revoked": 1})
|
||||
|
||||
c.Redirect("/auth/devices?success="+url.QueryEscape("已将该设备下线"), 302)
|
||||
}
|
||||
Reference in New Issue
Block a user