diff --git a/Makefile b/Makefile index 31080637..d7b55693 100644 --- a/Makefile +++ b/Makefile @@ -19,3 +19,6 @@ stop: migrate: ./bin/migrator --changeVersion=${v} + +run-studygolang: + cd src/server/studygolang; go run `ls | grep -v windows`; cd - diff --git a/env.sh b/env.sh new file mode 100644 index 00000000..69044b9d --- /dev/null +++ b/env.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env bash + +DIR=`pwd` +export GOPATH= +export GOPATH=$DIR +export PATH=$PATH:$DIR/bin diff --git a/src/http/middleware/admin.go b/src/http/middleware/admin.go index f16b057c..e72f4086 100644 --- a/src/http/middleware/admin.go +++ b/src/http/middleware/admin.go @@ -22,11 +22,7 @@ func AdminAuth() echo.MiddlewareFunc { return ctx.HTML(http.StatusForbidden, `403 Forbidden`) } - if err := next(ctx); err != nil { - return err - } - - return nil + return next(ctx) } } } diff --git a/src/http/middleware/csrf.go b/src/http/middleware/csrf.go new file mode 100644 index 00000000..946c44da --- /dev/null +++ b/src/http/middleware/csrf.go @@ -0,0 +1,66 @@ +// Copyright 2017 The StudyGolang Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +// http://studygolang.com +// Author: momaek momaek17@gmail.com + +package middleware + +import ( + "net/http" + "net/url" + "util" + + "github.com/labstack/echo" +) + +// ErrorRet 如果是 ajax 请求,返回前端错误信息的通用结构体 +type ErrorRet struct { + OK int `json:"ok"` + Error string `json:"error"` +} + +// CsrfRefererFilter 通过 referer 过滤csrf请求 +func CsrfRefererFilter() echo.MiddlewareFunc { + return func(next echo.HandlerFunc) echo.HandlerFunc { + return func(ctx echo.Context) (err error) { + req := ctx.Request() + can := false + + defer func() { + if can { + err = next(ctx) + } else { + if util.IsAjax(ctx) { + ctx.JSON(499, &ErrorRet{0, "CSRF Detected"}) + } else { + ctx.String(499, "CSRF Detected") + } + } + }() + + switch req.Method() { + case http.MethodGet, http.MethodHead: + can = true + return + } + + referer := req.Referer() + if len(referer) == 0 { + return + } + + u, err := url.Parse(referer) + if err != nil { + return + } + + if u.Host != req.Host() { + return + } + + can = true + return + } + } +} diff --git a/src/logic/user.go b/src/logic/user.go index 33e2aee3..2ff14b8f 100644 --- a/src/logic/user.go +++ b/src/logic/user.go @@ -370,6 +370,8 @@ func (UserLogic) Total() int64 { var ( ErrUsername = errors.New("用户名不存在") ErrPasswd = errors.New("密码错误") + + ErrUnameOrPwd = errors.New("用户名或密码错误") ) // Login 登录;成功返回用户登录信息(user_login) @@ -385,7 +387,7 @@ func (self UserLogic) Login(ctx context.Context, username, passwd string) (*mode // 校验用户 if userLogin.Uid == 0 { objLog.Infof("user %q is not exists!", username) - return nil, ErrUsername + return nil, ErrUnameOrPwd } // 检验用户状态是否正常(未激活的可以登录,但不能发布信息) @@ -405,7 +407,7 @@ func (self UserLogic) Login(ctx context.Context, username, passwd string) (*mode objLog.Debugf("passwd: %s, passcode: %s, md5passwd: %s, dbpasswd: %s", passwd, userLogin.Passcode, md5Passwd, userLogin.Passwd) if md5Passwd != userLogin.Passwd { objLog.Infof("用户名 %q 填写的密码错误", username) - return nil, ErrPasswd + return nil, ErrUnameOrPwd } go func() { diff --git a/src/server/studygolang/main.go b/src/server/studygolang/main.go index afca1848..1f965381 100644 --- a/src/server/studygolang/main.go +++ b/src/server/studygolang/main.go @@ -62,6 +62,7 @@ func main() { serveStatic(e) e.Use(thirdmw.EchoLogger()) + e.Use(pwm.CsrfRefererFilter()) e.Use(mw.Recover()) e.Use(pwm.Installed(filterPrefixs)) e.Use(pwm.HTTPError())