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]
 | 
					[security]
 | 
				
			||||||
; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!!
 | 
					; !!CHANGE THIS TO KEEP YOUR USER DATA SAFE!!
 | 
				
			||||||
SECRET_KEY = !#@FDEWREWR&*(
 | 
					SECRET_KEY = !#@FDEWREWR&*(
 | 
				
			||||||
 | 
					; Auto-login remember days
 | 
				
			||||||
 | 
					LOGIN_REMEMBER_DAYS = 7
 | 
				
			||||||
 | 
					COOKIE_USERNAME = gogs_awesome
 | 
				
			||||||
 | 
					COOKIE_REMEMBER_NAME = gogs_incredible
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[service]
 | 
					[service]
 | 
				
			||||||
ACTIVE_CODE_LIVE_MINUTES = 180
 | 
					ACTIVE_CODE_LIVE_MINUTES = 180
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,6 +61,7 @@ func (f *RegisterForm) Validate(errors *binding.Errors, req *http.Request, conte
 | 
				
			|||||||
type LogInForm struct {
 | 
					type LogInForm struct {
 | 
				
			||||||
	UserName string `form:"username" binding:"Required;AlphaDash;MaxSize(30)"`
 | 
						UserName string `form:"username" binding:"Required;AlphaDash;MaxSize(30)"`
 | 
				
			||||||
	Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"`
 | 
						Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"`
 | 
				
			||||||
 | 
						Remember string `form:"remember"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (f *LogInForm) Name(field string) string {
 | 
					func (f *LogInForm) Name(field string) string {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -38,6 +38,10 @@ var (
 | 
				
			|||||||
	RunUser      string
 | 
						RunUser      string
 | 
				
			||||||
	RepoRootPath string
 | 
						RepoRootPath string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						LogInRememberDays  int
 | 
				
			||||||
 | 
						CookieUserName     string
 | 
				
			||||||
 | 
						CookieRememberName string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Cfg         *goconfig.ConfigFile
 | 
						Cfg         *goconfig.ConfigFile
 | 
				
			||||||
	MailService *Mailer
 | 
						MailService *Mailer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -252,6 +256,10 @@ func NewConfigContext() {
 | 
				
			|||||||
	SecretKey = Cfg.MustValue("security", "SECRET_KEY")
 | 
						SecretKey = Cfg.MustValue("security", "SECRET_KEY")
 | 
				
			||||||
	RunUser = Cfg.MustValue("", "RUN_USER")
 | 
						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")
 | 
						PictureService = Cfg.MustValue("picture", "SERVICE")
 | 
				
			||||||
	PictureRootPath = Cfg.MustValue("picture", "PATH")
 | 
						PictureRootPath = Cfg.MustValue("picture", "PATH")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,9 +5,14 @@
 | 
				
			|||||||
package middleware
 | 
					package middleware
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"crypto/hmac"
 | 
				
			||||||
 | 
						"crypto/sha1"
 | 
				
			||||||
 | 
						"encoding/base64"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"html/template"
 | 
						"html/template"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/codegangsta/martini"
 | 
						"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())
 | 
						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 {
 | 
					func (ctx *Context) CsrfToken() string {
 | 
				
			||||||
	if len(ctx.csrfToken) > 0 {
 | 
						if len(ctx.csrfToken) > 0 {
 | 
				
			||||||
		return ctx.csrfToken
 | 
							return ctx.csrfToken
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -77,7 +77,39 @@ func SignIn(ctx *middleware.Context, form auth.LogInForm) {
 | 
				
			|||||||
	ctx.Data["Title"] = "Log In"
 | 
						ctx.Data["Title"] = "Log In"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.Req.Method == "GET" {
 | 
						if ctx.Req.Method == "GET" {
 | 
				
			||||||
		ctx.HTML(200, "user/signin")
 | 
							// 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
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -89,6 +121,7 @@ func SignIn(ctx *middleware.Context, form auth.LogInForm) {
 | 
				
			|||||||
	user, err := models.LoginUserPlain(form.UserName, form.Password)
 | 
						user, err := models.LoginUserPlain(form.UserName, form.Password)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		if err == models.ErrUserNotExist {
 | 
							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)
 | 
								ctx.RenderWithErr("Username or password is not correct", "user/signin", &form)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -97,6 +130,13 @@ func SignIn(ctx *middleware.Context, form auth.LogInForm) {
 | 
				
			|||||||
		return
 | 
							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("userId", user.Id)
 | 
				
			||||||
	ctx.Session.Set("userName", user.Name)
 | 
						ctx.Session.Set("userName", user.Name)
 | 
				
			||||||
	ctx.Redirect("/")
 | 
						ctx.Redirect("/")
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,17 @@
 | 
				
			|||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        </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="form-group">
 | 
				
			||||||
            <div class="col-md-offset-4 col-md-6">
 | 
					            <div class="col-md-offset-4 col-md-6">
 | 
				
			||||||
                <button type="submit" class="btn btn-lg btn-primary">Log In</button>
 | 
					                <button type="submit" class="btn btn-lg btn-primary">Log In</button>
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user