diff --git a/.gitignore b/.gitignore index ad27cc8be..d201223ef 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ gogs *.db *.log custom/ +data/ .vendor/ .idea/ *.iml \ No newline at end of file diff --git a/conf/app.ini b/conf/app.ini index cf99c9da0..cf2ae31d8 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -72,6 +72,33 @@ INTERVAL = 60 ; memcache: "127.0.0.1:11211" HOST = +[session] +; Either "memory", "file", "redis" or "mysql", default is "memory" +PROVIDER = file +; provider config +; memory: not have any config yet +; file: session file path +; e.g. tmp/sessions +; redis: config like redis server addr,poolSize,password +; e.g. 127.0.0.1:6379,100,astaxie +; mysql: go-sql-driver/mysql dsn config string +; e.g. root:password@/session_table +PROVIDER_CONFIG = data/sessions +; session cookie name +COOKIE_NAME = i_like_gogits +; if you use session in https only, default is false +COOKIE_SECURE = false +; enable set cookie, default is true +ENABLE_SET_COOKIE = true +; session gc time interval, default is 86400 +GC_INTERVAL_TIME = 86400 +; session life time, default is 86400 +SESSION_LIFE_TIME = 86400 +; session id hash func, default is sha1 +SESSION_ID_HASHFUNC = sha1 +; session hash key, default is use random string +SESSION_ID_HASHKEY = + [picture] ; The place to picture data, either "server" or "qiniu", default is "server" SERVICE = server diff --git a/modules/auth/user.go b/modules/auth/user.go index f8d8f6614..cb8db1b29 100644 --- a/modules/auth/user.go +++ b/modules/auth/user.go @@ -9,7 +9,8 @@ import ( "reflect" "github.com/codegangsta/martini" - "github.com/martini-contrib/sessions" + + "github.com/gogits/session" "github.com/gogits/binding" @@ -19,7 +20,7 @@ import ( ) // SignedInId returns the id of signed in user. -func SignedInId(session sessions.Session) int64 { +func SignedInId(session session.SessionStore) int64 { userId := session.Get("userId") if userId == nil { return 0 @@ -34,7 +35,7 @@ func SignedInId(session sessions.Session) int64 { } // SignedInName returns the name of signed in user. -func SignedInName(session sessions.Session) string { +func SignedInName(session session.SessionStore) string { userName := session.Get("userName") if userName == nil { return "" @@ -46,7 +47,7 @@ func SignedInName(session sessions.Session) string { } // SignedInUser returns the user object of signed user. -func SignedInUser(session sessions.Session) *models.User { +func SignedInUser(session session.SessionStore) *models.User { id := SignedInId(session) if id <= 0 { return nil @@ -61,7 +62,7 @@ func SignedInUser(session sessions.Session) *models.User { } // IsSignedIn check if any user has signed in. -func IsSignedIn(session sessions.Session) bool { +func IsSignedIn(session session.SessionStore) bool { return SignedInId(session) > 0 } diff --git a/modules/base/conf.go b/modules/base/conf.go index 8c6ee6281..d5e27d043 100644 --- a/modules/base/conf.go +++ b/modules/base/conf.go @@ -16,6 +16,7 @@ import ( "github.com/Unknwon/goconfig" "github.com/gogits/cache" + "github.com/gogits/session" "github.com/gogits/gogs/modules/log" ) @@ -49,6 +50,10 @@ var ( LogMode string LogConfig string + + SessionProvider string + SessionConfig *session.Config + SessionManager *session.Manager ) var Service struct { @@ -164,6 +169,30 @@ func newCacheService() { log.Info("Cache Service Enabled") } +func newSessionService() { + SessionProvider = Cfg.MustValue("session", "PROVIDER", "memory") + + SessionConfig = new(session.Config) + SessionConfig.ProviderConfig = Cfg.MustValue("session", "PROVIDER_CONFIG") + SessionConfig.CookieName = Cfg.MustValue("session", "COOKIE_NAME", "i_like_gogits") + SessionConfig.CookieSecure = Cfg.MustBool("session", "COOKIE_SECURE") + SessionConfig.EnableSetCookie = Cfg.MustBool("session", "ENABLE_SET_COOKIE", true) + SessionConfig.GcIntervalTime = Cfg.MustInt64("session", "GC_INTERVAL_TIME", 86400) + SessionConfig.SessionLifeTime = Cfg.MustInt64("session", "SESSION_LIFE_TIME", 86400) + SessionConfig.SessionIDHashFunc = Cfg.MustValue("session", "SESSION_ID_HASHFUNC", "sha1") + SessionConfig.SessionIDHashKey = Cfg.MustValue("session", "SESSION_ID_HASHKEY") + + var err error + SessionManager, err = session.NewManager(SessionProvider, *SessionConfig) + if err != nil { + fmt.Printf("Init session system failed, provider: %s, %v\n", + SessionProvider, err) + os.Exit(2) + } + + log.Info("Session Service Enabled") +} + func newMailService() { // Check mailer setting. if Cfg.MustBool("mailer", "ENABLED") { @@ -234,6 +263,7 @@ func NewServices() { newService() newLogService() newCacheService() + newSessionService() newMailService() newRegisterMailService() } diff --git a/modules/middleware/context.go b/modules/middleware/context.go index a25a3dbbe..c958c1d6c 100644 --- a/modules/middleware/context.go +++ b/modules/middleware/context.go @@ -10,9 +10,9 @@ import ( "time" "github.com/codegangsta/martini" - "github.com/martini-contrib/sessions" "github.com/gogits/cache" + "github.com/gogits/session" "github.com/gogits/gogs/models" "github.com/gogits/gogs/modules/auth" @@ -27,7 +27,7 @@ type Context struct { p martini.Params Req *http.Request Res http.ResponseWriter - Session sessions.Session + Session session.SessionStore Cache cache.Cache User *models.User IsSigned bool @@ -92,21 +92,25 @@ func (ctx *Context) Handle(status int, title string, err error) { // InitContext initializes a classic context for a request. func InitContext() martini.Handler { - return func(res http.ResponseWriter, r *http.Request, c martini.Context, - session sessions.Session, rd *Render) { + return func(res http.ResponseWriter, r *http.Request, c martini.Context, rd *Render) { ctx := &Context{ c: c, // p: p, - Req: r, - Res: res, - Session: session, - Cache: base.Cache, - Render: rd, + Req: r, + Res: res, + Cache: base.Cache, + Render: rd, } + // start session + ctx.Session = base.SessionManager.SessionStart(res, r) + defer func() { + ctx.Session.SessionRelease(res) + }() + // Get user from session if logined. - user := auth.SignedInUser(session) + user := auth.SignedInUser(ctx.Session) ctx.User = user ctx.IsSigned = user != nil diff --git a/routers/user/user.go b/routers/user/user.go index d38eb1ceb..224469771 100644 --- a/routers/user/user.go +++ b/routers/user/user.go @@ -88,7 +88,7 @@ func SignIn(ctx *middleware.Context, form auth.LogInForm) { user, err := models.LoginUserPlain(form.UserName, form.Password) if err != nil { - if err.Error() == models.ErrUserNotExist.Error() { + if err == models.ErrUserNotExist { ctx.RenderWithErr("Username or password is not correct", "user/signin", &form) return } diff --git a/web.go b/web.go index 595b8f74e..ac5761d72 100644 --- a/web.go +++ b/web.go @@ -12,7 +12,6 @@ import ( "github.com/codegangsta/cli" "github.com/codegangsta/martini" - "github.com/martini-contrib/sessions" "github.com/gogits/binding" @@ -81,10 +80,6 @@ func runWeb(*cli.Context) { // Middlewares. m.Use(middleware.Renderer(middleware.RenderOptions{Funcs: []template.FuncMap{base.TemplateFuncs}})) - // TODO: should use other store because cookie store is not secure. - store := sessions.NewCookieStore([]byte("secret123")) - m.Use(sessions.Sessions("my_session", store)) - m.Use(middleware.InitContext()) reqSignIn := middleware.SignInRequire(true)