mirror of
				https://gitee.com/gitea/gitea
				synced 2025-11-04 08:30:25 +08:00 
			
		
		
		
	Add auto-login
This commit is contained in:
		@@ -34,6 +34,10 @@ PATH = data/gogs.db
 | 
			
		||||
[security]
 | 
			
		||||
; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!!
 | 
			
		||||
SECRET_KEY = !#@FDEWREWR&*(
 | 
			
		||||
; Auto-login remember days
 | 
			
		||||
LOGIN_REMEMBER_DAYS = 7
 | 
			
		||||
COOKIE_USERNAME = gogs_awesome
 | 
			
		||||
COOKIE_REMEMBER_NAME = gogs_incredible
 | 
			
		||||
 | 
			
		||||
[service]
 | 
			
		||||
ACTIVE_CODE_LIVE_MINUTES = 180
 | 
			
		||||
 
 | 
			
		||||
@@ -61,6 +61,7 @@ func (f *RegisterForm) Validate(errors *binding.Errors, req *http.Request, conte
 | 
			
		||||
type LogInForm struct {
 | 
			
		||||
	UserName string `form:"username" binding:"Required;AlphaDash;MaxSize(30)"`
 | 
			
		||||
	Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"`
 | 
			
		||||
	Remember string `form:"remember"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *LogInForm) Name(field string) string {
 | 
			
		||||
 
 | 
			
		||||
@@ -38,6 +38,10 @@ var (
 | 
			
		||||
	RunUser      string
 | 
			
		||||
	RepoRootPath string
 | 
			
		||||
 | 
			
		||||
	LogInRememberDays  int
 | 
			
		||||
	CookieUserName     string
 | 
			
		||||
	CookieRememberName string
 | 
			
		||||
 | 
			
		||||
	Cfg         *goconfig.ConfigFile
 | 
			
		||||
	MailService *Mailer
 | 
			
		||||
 | 
			
		||||
@@ -252,6 +256,10 @@ func NewConfigContext() {
 | 
			
		||||
	SecretKey = Cfg.MustValue("security", "SECRET_KEY")
 | 
			
		||||
	RunUser = Cfg.MustValue("", "RUN_USER")
 | 
			
		||||
 | 
			
		||||
	LogInRememberDays = Cfg.MustInt("security", "LOGIN_REMEMBER_DAYS")
 | 
			
		||||
	CookieUserName = Cfg.MustValue("security", "COOKIE_USERNAME")
 | 
			
		||||
	CookieRememberName = Cfg.MustValue("security", "COOKIE_REMEMBER_NAME")
 | 
			
		||||
 | 
			
		||||
	PictureService = Cfg.MustValue("picture", "SERVICE")
 | 
			
		||||
	PictureRootPath = Cfg.MustValue("picture", "PATH")
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,14 @@
 | 
			
		||||
package middleware
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"crypto/hmac"
 | 
			
		||||
	"crypto/sha1"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"html/template"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/codegangsta/martini"
 | 
			
		||||
@@ -155,6 +160,44 @@ func (ctx *Context) SetCookie(name string, value string, others ...interface{})
 | 
			
		||||
	ctx.Res.Header().Add("Set-Cookie", cookie.String())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get secure cookie from request by a given key.
 | 
			
		||||
func (ctx *Context) GetSecureCookie(Secret, key string) (string, bool) {
 | 
			
		||||
	val := ctx.GetCookie(key)
 | 
			
		||||
	if val == "" {
 | 
			
		||||
		return "", false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	parts := strings.SplitN(val, "|", 3)
 | 
			
		||||
 | 
			
		||||
	if len(parts) != 3 {
 | 
			
		||||
		return "", false
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vs := parts[0]
 | 
			
		||||
	timestamp := parts[1]
 | 
			
		||||
	sig := parts[2]
 | 
			
		||||
 | 
			
		||||
	h := hmac.New(sha1.New, []byte(Secret))
 | 
			
		||||
	fmt.Fprintf(h, "%s%s", vs, timestamp)
 | 
			
		||||
 | 
			
		||||
	if fmt.Sprintf("%02x", h.Sum(nil)) != sig {
 | 
			
		||||
		return "", false
 | 
			
		||||
	}
 | 
			
		||||
	res, _ := base64.URLEncoding.DecodeString(vs)
 | 
			
		||||
	return string(res), true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set Secure cookie for response.
 | 
			
		||||
func (ctx *Context) SetSecureCookie(Secret, name, value string, others ...interface{}) {
 | 
			
		||||
	vs := base64.URLEncoding.EncodeToString([]byte(value))
 | 
			
		||||
	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
 | 
			
		||||
	h := hmac.New(sha1.New, []byte(Secret))
 | 
			
		||||
	fmt.Fprintf(h, "%s%s", vs, timestamp)
 | 
			
		||||
	sig := fmt.Sprintf("%02x", h.Sum(nil))
 | 
			
		||||
	cookie := strings.Join([]string{vs, timestamp, sig}, "|")
 | 
			
		||||
	ctx.SetCookie(name, cookie, others...)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ctx *Context) CsrfToken() string {
 | 
			
		||||
	if len(ctx.csrfToken) > 0 {
 | 
			
		||||
		return ctx.csrfToken
 | 
			
		||||
 
 | 
			
		||||
@@ -77,10 +77,42 @@ func SignIn(ctx *middleware.Context, form auth.LogInForm) {
 | 
			
		||||
	ctx.Data["Title"] = "Log In"
 | 
			
		||||
 | 
			
		||||
	if ctx.Req.Method == "GET" {
 | 
			
		||||
		// Check auto-login.
 | 
			
		||||
		userName := ctx.GetCookie(base.CookieUserName)
 | 
			
		||||
		if len(userName) == 0 {
 | 
			
		||||
			ctx.HTML(200, "user/signin")
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		isSucceed := false
 | 
			
		||||
		defer func() {
 | 
			
		||||
			if !isSucceed {
 | 
			
		||||
				log.Trace("%s auto-login cookie cleared: %s", ctx.Req.RequestURI, userName)
 | 
			
		||||
				ctx.SetCookie(base.CookieUserName, "", -1)
 | 
			
		||||
				ctx.SetCookie(base.CookieRememberName, "", -1)
 | 
			
		||||
			}
 | 
			
		||||
		}()
 | 
			
		||||
 | 
			
		||||
		user, err := models.GetUserByName(userName)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.HTML(200, "user/signin")
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		secret := base.EncodeMd5(user.Rands + user.Passwd)
 | 
			
		||||
		value, _ := ctx.GetSecureCookie(secret, base.CookieRememberName)
 | 
			
		||||
		if value != user.Name {
 | 
			
		||||
			ctx.HTML(200, "user/signin")
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		isSucceed = true
 | 
			
		||||
		ctx.Session.Set("userId", user.Id)
 | 
			
		||||
		ctx.Session.Set("userName", user.Name)
 | 
			
		||||
		ctx.Redirect("/")
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if hasErr, ok := ctx.Data["HasError"]; ok && hasErr.(bool) {
 | 
			
		||||
		ctx.HTML(200, "user/signin")
 | 
			
		||||
		return
 | 
			
		||||
@@ -89,6 +121,7 @@ func SignIn(ctx *middleware.Context, form auth.LogInForm) {
 | 
			
		||||
	user, err := models.LoginUserPlain(form.UserName, form.Password)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if err == models.ErrUserNotExist {
 | 
			
		||||
			log.Trace("%s Log in failed: %s/%s", ctx.Req.RequestURI, form.UserName, form.Password)
 | 
			
		||||
			ctx.RenderWithErr("Username or password is not correct", "user/signin", &form)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
@@ -97,6 +130,13 @@ func SignIn(ctx *middleware.Context, form auth.LogInForm) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if form.Remember == "on" {
 | 
			
		||||
		secret := base.EncodeMd5(user.Rands + user.Passwd)
 | 
			
		||||
		days := 86400 * base.LogInRememberDays
 | 
			
		||||
		ctx.SetCookie(base.CookieUserName, user.Name, days)
 | 
			
		||||
		ctx.SetSecureCookie(secret, base.CookieRememberName, user.Name, days)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.Session.Set("userId", user.Id)
 | 
			
		||||
	ctx.Session.Set("userName", user.Name)
 | 
			
		||||
	ctx.Redirect("/")
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,17 @@
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="form-group">
 | 
			
		||||
            <div class="col-md-6 col-md-offset-4">
 | 
			
		||||
                <div class="checkbox">
 | 
			
		||||
                    <label>
 | 
			
		||||
                        <input type="checkbox" name="remember" {{if .remember}}checked{{end}}>
 | 
			
		||||
                        <strong>Remember me</strong>
 | 
			
		||||
                    </label>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="form-group">
 | 
			
		||||
            <div class="col-md-offset-4 col-md-6">
 | 
			
		||||
                <button type="submit" class="btn btn-lg btn-primary">Log In</button>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user