Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d6db896

Browse files
committed
IP 黑名单
1 parent b0415aa commit d6db896

File tree

10 files changed

+128
-16
lines changed

10 files changed

+128
-16
lines changed

config/db.sql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ CREATE TABLE IF NOT EXISTS `user_login` (
115115
`username` varchar(20) NOT NULL COMMENT '用户名',
116116
`passcode` char(12) NOT NULL DEFAULT '' COMMENT '加密随机数',
117117
`passwd` char(32) NOT NULL DEFAULT '' COMMENT 'md5密码',
118+
`login_ip` varchar(31) NOT NULL DEFAULT '' COMMENT '最后登录 IP',
118119
`login_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后一次登录时间(主动登录或cookie登录)',
119120
PRIMARY KEY (`uid`),
120121
UNIQUE KEY (`username`),

src/http/controller/admin/user.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package admin
88

99
import (
1010
"logic"
11+
"model"
1112

1213
"github.com/labstack/echo"
1314
"github.com/polaris1119/goutils"
@@ -21,6 +22,7 @@ func (self UserController) RegisterRoute(g *echo.Group) {
2122
g.POST("/user/user/query.html", self.UserQuery)
2223
g.GET("/user/user/detail", self.Detail)
2324
g.POST("/user/user/modify", self.Modify)
25+
g.POST("/user/user/add_black", self.AddBlack)
2426
}
2527

2628
// UserList 所有用户(分页)
@@ -78,3 +80,16 @@ func (UserController) Modify(ctx echo.Context) error {
7880
}
7981
return success(ctx, nil)
8082
}
83+
84+
func (UserController) AddBlack(ctx echo.Context) error {
85+
uid := goutils.MustInt(ctx.FormValue("uid"))
86+
err := logic.DefaultUser.UpdateUserStatus(ctx, uid, model.UserStatusOutage)
87+
if err != nil {
88+
return fail(ctx, 1, err.Error())
89+
}
90+
91+
// 获取用户上次登录 IP
92+
logic.DefaultRisk.AddBlackIPByUID(uid)
93+
94+
return success(ctx, nil)
95+
}

src/http/middleware/login.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ import (
2121

2222
"github.com/gorilla/context"
2323
"github.com/labstack/echo"
24+
"github.com/polaris1119/goutils"
25+
26+
netcontext "golang.org/x/net/context"
2427
)
2528

2629
// AutoLogin 用于 echo 框架的自动登录和通过 cookie 获取用户信息
@@ -33,9 +36,16 @@ func AutoLogin() echo.MiddlewareFunc {
3336
ctx.Set("req_start_time", time.Now())
3437

3538
var getCurrentUser = func(usernameOrId interface{}) {
39+
ip := goutils.RemoteIp(Request(ctx))
40+
// IP 黑名单,不让登录
41+
if logic.DefaultRisk.IsBlackIP(ip) {
42+
return
43+
}
44+
3645
if db.MasterDB != nil {
46+
valCtx := netcontext.WithValue(ctx, "ip", ip)
3747
// TODO: 考虑缓存,或延迟查询,避免每次都查询
38-
user := logic.DefaultUser.FindCurrentUser(ctx, usernameOrId)
48+
user := logic.DefaultUser.FindCurrentUser(valCtx, usernameOrId)
3949
if user.Uid != 0 {
4050
ctx.Set("user", user)
4151

src/http/middleware/sensitive.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ import (
1414
"model"
1515

1616
"github.com/labstack/echo"
17+
"github.com/labstack/echo/engine/standard"
1718
"github.com/polaris1119/config"
19+
"github.com/polaris1119/goutils"
1820
"github.com/polaris1119/logger"
1921
)
2022

@@ -43,6 +45,8 @@ func Sensivite() echo.MiddlewareFunc {
4345
// 把账号冻结
4446
logic.DefaultUser.UpdateUserStatus(ctx, user.Uid, model.UserStatusFreeze)
4547
logger.Infoln("user=", user.Uid, "publish ad, title=", title, ". freeze")
48+
// IP 加入黑名单
49+
addBlackIP(ctx)
4650
return ctx.String(http.StatusOK, `{"ok":0,"error":"对不起,您的账号已被冻结!"}`)
4751
}
4852
}
@@ -52,6 +56,8 @@ func Sensivite() echo.MiddlewareFunc {
5256
// 把账号冻结
5357
logic.DefaultUser.UpdateUserStatus(ctx, user.Uid, model.UserStatusFreeze)
5458
logger.Infoln("user=", user.Uid, "publish ad, title=", title, ";content=", content, ". freeze")
59+
// IP 加入黑名单
60+
addBlackIP(ctx)
5561
return ctx.String(http.StatusOK, `{"ok":0,"error":"对不起,您的账号已被冻结!"}`)
5662
}
5763

@@ -97,3 +103,11 @@ func hasSensitiveChar(title, sensitive string) bool {
97103

98104
return true
99105
}
106+
107+
func addBlackIP(ctx echo.Context) {
108+
req := ctx.Request().(*standard.Request).Request
109+
110+
ip := goutils.RemoteIp(req)
111+
112+
logic.DefaultRisk.AddBlackIP(ip)
113+
}

src/logic/risk.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2016 The StudyGolang Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
// http://studygolang.com
5+
// Author:polaris [email protected]
6+
7+
package logic
8+
9+
import (
10+
. "db"
11+
"model"
12+
13+
"github.com/polaris1119/nosql"
14+
)
15+
16+
type RiskLogic struct{}
17+
18+
var DefaultRisk = RiskLogic{}
19+
20+
// AddBlackIP 加入 IP 黑名单
21+
func (RiskLogic) AddBlackIP(ip string) error {
22+
redisClient := nosql.NewRedisClient()
23+
defer redisClient.Close()
24+
25+
key := "black:ip"
26+
return redisClient.HSET(key, ip, "1")
27+
}
28+
29+
// AddBlackIPByUID 通过用户 UID 将最后一次登录 IP 加入黑名单
30+
func (self RiskLogic) AddBlackIPByUID(uid int) error {
31+
userLogin := &model.UserLogin{}
32+
_, err := MasterDB.Where("uid=?", uid).Get(userLogin)
33+
if err != nil {
34+
return err
35+
}
36+
37+
if userLogin.LoginIp != "" {
38+
return self.AddBlackIP(userLogin.LoginIp)
39+
}
40+
41+
return nil
42+
}
43+
44+
// IsBlackIP 是否是 IP 黑名单
45+
func (RiskLogic) IsBlackIP(ip string) bool {
46+
redisClient := nosql.NewRedisClient()
47+
defer redisClient.Close()
48+
49+
key := "black:ip"
50+
val, err := redisClient.HGET(key, ip)
51+
if err != nil {
52+
return false
53+
}
54+
55+
return val == "1"
56+
}

src/logic/searcher.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ func (self SearcherLogic) IndexingArticle(isAll bool) {
5858
if isAll {
5959
err = MasterDB.Where("id>?", id).Limit(self.maxRows).OrderBy("id ASC").Find(&articleList)
6060
} else {
61-
timeAgo := time.Now().Add(-5 * time.Minute).Format("2006-01-02 15:04:05")
61+
timeAgo := time.Now().Add(-2 * time.Minute).Format("2006-01-02 15:04:05")
6262
err = MasterDB.Where("mtime>?", timeAgo).Find(&articleList)
6363
}
6464
if err != nil {
@@ -120,7 +120,7 @@ func (self SearcherLogic) IndexingTopic(isAll bool) {
120120
if isAll {
121121
err = MasterDB.Where("tid>?", id).OrderBy("tid ASC").Limit(self.maxRows).Find(&topicList)
122122
} else {
123-
timeAgo := time.Now().Add(-5 * time.Minute).Format("2006-01-02 15:04:05")
123+
timeAgo := time.Now().Add(-2 * time.Minute).Format("2006-01-02 15:04:05")
124124
err = MasterDB.Where("mtime>?", timeAgo).Find(&topicList)
125125
}
126126
if err != nil {
@@ -189,7 +189,7 @@ func (self SearcherLogic) IndexingResource(isAll bool) {
189189
if isAll {
190190
err = MasterDB.Where("id>?", id).OrderBy("id ASC").Limit(self.maxRows).Find(&resourceList)
191191
} else {
192-
timeAgo := time.Now().Add(-5 * time.Minute).Format("2006-01-02 15:04:05")
192+
timeAgo := time.Now().Add(-2 * time.Minute).Format("2006-01-02 15:04:05")
193193
err = MasterDB.Where("mtime>?", timeAgo).Find(&resourceList)
194194
}
195195
if err != nil {
@@ -256,7 +256,7 @@ func (self SearcherLogic) IndexingOpenProject(isAll bool) {
256256
if isAll {
257257
err = MasterDB.Where("id>?", id).OrderBy("id ASC").Limit(self.maxRows).Find(&projectList)
258258
} else {
259-
timeAgo := time.Now().Add(-5 * time.Minute).Format("2006-01-02 15:04:05")
259+
timeAgo := time.Now().Add(-2 * time.Minute).Format("2006-01-02 15:04:05")
260260
err = MasterDB.Where("mtime>?", timeAgo).Find(&projectList)
261261
}
262262
if err != nil {

src/logic/user.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,15 @@ func (self UserLogic) Update(ctx context.Context, me *model.Me, form url.Values)
165165
}
166166

167167
// UpdateUserStatus 更新用户状态
168-
func (UserLogic) UpdateUserStatus(ctx context.Context, uid, status int) {
168+
func (UserLogic) UpdateUserStatus(ctx context.Context, uid, status int) error {
169169
objLog := GetLogger(ctx)
170170

171171
_, err := MasterDB.Table(new(model.User)).Id(uid).Update(map[string]interface{}{"status": status})
172172
if err != nil {
173173
objLog.Errorf("更新用户 【%d】 状态失败:%s", uid, err)
174174
}
175+
176+
return err
175177
}
176178

177179
// ChangeAvatar 更换头像
@@ -320,7 +322,8 @@ func (self UserLogic) FindCurrentUser(ctx context.Context, username interface{})
320322
}
321323

322324
// TODO: 先每次都记录登录时间
323-
go self.RecordLoginTime(user.Username)
325+
ip := ctx.Value("ip")
326+
go self.RecordLogin(user.Username, ip)
324327

325328
if user.IsRoot {
326329
me.IsAdmin = true
@@ -425,7 +428,8 @@ func (self UserLogic) Login(ctx context.Context, username, passwd string) (*mode
425428

426429
go func() {
427430
self.IncrUserWeight("uid", userLogin.Uid, 1)
428-
self.RecordLoginTime(username)
431+
ip := ctx.Value("ip")
432+
self.RecordLogin(username, ip)
429433
}()
430434

431435
return userLogin, nil
@@ -546,12 +550,18 @@ func (UserLogic) DecrUserWeight(field string, value interface{}, divide int) {
546550
}
547551
}
548552

549-
// RecordLoginTime 记录用户最后登录时间
550-
func (UserLogic) RecordLoginTime(username string) error {
553+
// RecordLogin 记录用户最后登录时间和 IP
554+
func (UserLogic) RecordLogin(username string, ipinter interface{}) error {
555+
change := map[string]interface{}{
556+
"login_time": time.Now(),
557+
}
558+
if ip, ok := ipinter.(string); ok && ip != "" {
559+
change["login_ip"] = ip
560+
}
551561
_, err := MasterDB.Table(new(model.UserLogin)).Where("username=?", username).
552-
Update(map[string]interface{}{"login_time": time.Now()})
562+
Update(change)
553563
if err != nil {
554-
logger.Errorf("记录用户 %q 登录时间错误:%s", username, err)
564+
logger.Errorf("记录用户 %q 登录错误:%s", username, err)
555565
}
556566
return err
557567
}

src/model/user.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@ import (
2020
type UserLogin struct {
2121
Uid int `json:"uid" xorm:"pk"`
2222
Username string `json:"username"`
23+
Passcode string `json:"passcode"` // 加密随机串
2324
Passwd string `json:"passwd"`
2425
Email string `json:"email"`
26+
LoginIp string `json:"login_ip"`
2527
LoginTime time.Time `json:"login_time" xorm:"<-"`
26-
Passcode string `json:"passcode"` // 加密随机串
2728
}
2829

2930
func (this *UserLogin) TableName() string {

template/admin/user/query.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ <h4>总数:{{ .total }}</h4><br/>
2525
<td>{{ .Ctime }}</td>
2626
<td class="actions">
2727
<a href="/admin/user/user/detail?uid={{ .Uid }}" target="_blank">详情</a>
28+
<a data-type="ajax-submit" href="#"
29+
ajax-action="/admin/user/user/add_black?uid={{ .Uid }}"
30+
ajax-hint="是否确认要加黑?"
31+
success-hint="加黑成功"
32+
callback="delCallback">加黑</a>
2833
</td>
2934
</tr>
3035
{{end}}
@@ -43,4 +48,4 @@ <h4>总数:{{ .total }}</h4><br/>
4348
<input type="hidden" id="cur_page" value="{{ .page }}"/>
4449
<input type="hidden" id="limit" value="{{ .limit }}"/>
4550

46-
{{end}}
51+
{{end}}

template/cssjs/ckeditor.js.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
<script type="text/javascript" src="//cdn.ckeditor.com/4.6.2/standard-all/ckeditor.js"></script>
1+
<script type="text/javascript" src="https://cdn.staticfile.org/ckeditor/4.6.2/ckeditor.js"></script>
22
<script type="text/javascript" src="{{.static_domain}}/static/ckeditor/config.js"></script>
3-
<script type="text/javascript" src="{{.static_domain}}/static/ckeditor/article.js"></script>
3+
<script type="text/javascript" src="{{.static_domain}}/static/ckeditor/article.js"></script>

0 commit comments

Comments
 (0)