+ config: "web_session_ttl" setting
This commit is contained in:
parent
0d4dce5c79
commit
c9a6e4e018
25
home/auth.go
25
home/auth.go
@ -18,7 +18,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const cookieTTL = 365 * 24 // in hours
|
const cookieTTL = 365 * 24 // in hours
|
||||||
const expireTime = 30 * 24 // in hours
|
|
||||||
|
|
||||||
type session struct {
|
type session struct {
|
||||||
userName string
|
userName string
|
||||||
@ -56,10 +55,11 @@ func (s *session) deserialize(data []byte) bool {
|
|||||||
|
|
||||||
// Auth - global object
|
// Auth - global object
|
||||||
type Auth struct {
|
type Auth struct {
|
||||||
db *bbolt.DB
|
db *bbolt.DB
|
||||||
sessions map[string]*session // session name -> session data
|
sessions map[string]*session // session name -> session data
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
users []User
|
users []User
|
||||||
|
sessionTTL uint32 // in seconds
|
||||||
}
|
}
|
||||||
|
|
||||||
// User object
|
// User object
|
||||||
@ -69,8 +69,9 @@ type User struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// InitAuth - create a global object
|
// InitAuth - create a global object
|
||||||
func InitAuth(dbFilename string, users []User) *Auth {
|
func InitAuth(dbFilename string, users []User, sessionTTL uint32) *Auth {
|
||||||
a := Auth{}
|
a := Auth{}
|
||||||
|
a.sessionTTL = sessionTTL
|
||||||
a.sessions = make(map[string]*session)
|
a.sessions = make(map[string]*session)
|
||||||
rand.Seed(time.Now().UTC().Unix())
|
rand.Seed(time.Now().UTC().Unix())
|
||||||
var err error
|
var err error
|
||||||
@ -233,7 +234,7 @@ func (a *Auth) CheckSession(sess string) int {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
newExpire := now + expireTime*60*60
|
newExpire := now + a.sessionTTL
|
||||||
if s.expire/(24*60*60) != newExpire/(24*60*60) {
|
if s.expire/(24*60*60) != newExpire/(24*60*60) {
|
||||||
// update expiration time once a day
|
// update expiration time once a day
|
||||||
update = true
|
update = true
|
||||||
@ -270,8 +271,8 @@ func getSession(u *User) []byte {
|
|||||||
return hash[:]
|
return hash[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func httpCookie(req loginJSON) string {
|
func (a *Auth) httpCookie(req loginJSON) string {
|
||||||
u := config.auth.UserFind(req.Name, req.Password)
|
u := a.UserFind(req.Name, req.Password)
|
||||||
if len(u.Name) == 0 {
|
if len(u.Name) == 0 {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -286,8 +287,8 @@ func httpCookie(req loginJSON) string {
|
|||||||
|
|
||||||
s := session{}
|
s := session{}
|
||||||
s.userName = u.Name
|
s.userName = u.Name
|
||||||
s.expire = uint32(now.Unix()) + expireTime*60*60
|
s.expire = uint32(now.Unix()) + a.sessionTTL
|
||||||
config.auth.addSession(sess, &s)
|
a.addSession(sess, &s)
|
||||||
|
|
||||||
return fmt.Sprintf("session=%s; Path=/; HttpOnly; Expires=%s", hex.EncodeToString(sess), expstr)
|
return fmt.Sprintf("session=%s; Path=/; HttpOnly; Expires=%s", hex.EncodeToString(sess), expstr)
|
||||||
}
|
}
|
||||||
@ -300,7 +301,7 @@ func handleLogin(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
cookie := httpCookie(req)
|
cookie := config.auth.httpCookie(req)
|
||||||
if len(cookie) == 0 {
|
if len(cookie) == 0 {
|
||||||
time.Sleep(1 * time.Second)
|
time.Sleep(1 * time.Second)
|
||||||
httpError(w, http.StatusBadRequest, "invalid login or password")
|
httpError(w, http.StatusBadRequest, "invalid login or password")
|
||||||
|
@ -27,7 +27,7 @@ func TestAuth(t *testing.T) {
|
|||||||
users := []User{
|
users := []User{
|
||||||
User{Name: "name", PasswordHash: "$2y$05$..vyzAECIhJPfaQiOK17IukcQnqEgKJHy0iETyYqxn3YXJl8yZuo2"},
|
User{Name: "name", PasswordHash: "$2y$05$..vyzAECIhJPfaQiOK17IukcQnqEgKJHy0iETyYqxn3YXJl8yZuo2"},
|
||||||
}
|
}
|
||||||
a := InitAuth(fn, nil)
|
a := InitAuth(fn, nil, 60)
|
||||||
s := session{}
|
s := session{}
|
||||||
|
|
||||||
user := User{Name: "name"}
|
user := User{Name: "name"}
|
||||||
@ -54,7 +54,7 @@ func TestAuth(t *testing.T) {
|
|||||||
a.Close()
|
a.Close()
|
||||||
|
|
||||||
// load saved session
|
// load saved session
|
||||||
a = InitAuth(fn, users)
|
a = InitAuth(fn, users, 60)
|
||||||
|
|
||||||
// the session is still alive
|
// the session is still alive
|
||||||
assert.True(t, a.CheckSession(sessStr) == 0)
|
assert.True(t, a.CheckSession(sessStr) == 0)
|
||||||
@ -69,7 +69,7 @@ func TestAuth(t *testing.T) {
|
|||||||
time.Sleep(3 * time.Second)
|
time.Sleep(3 * time.Second)
|
||||||
|
|
||||||
// load and remove expired sessions
|
// load and remove expired sessions
|
||||||
a = InitAuth(fn, users)
|
a = InitAuth(fn, users, 60)
|
||||||
assert.True(t, a.CheckSession(sessStr) == -1)
|
assert.True(t, a.CheckSession(sessStr) == -1)
|
||||||
|
|
||||||
a.Close()
|
a.Close()
|
||||||
@ -100,7 +100,7 @@ func TestAuthHTTP(t *testing.T) {
|
|||||||
users := []User{
|
users := []User{
|
||||||
User{Name: "name", PasswordHash: "$2y$05$..vyzAECIhJPfaQiOK17IukcQnqEgKJHy0iETyYqxn3YXJl8yZuo2"},
|
User{Name: "name", PasswordHash: "$2y$05$..vyzAECIhJPfaQiOK17IukcQnqEgKJHy0iETyYqxn3YXJl8yZuo2"},
|
||||||
}
|
}
|
||||||
config.auth = InitAuth(fn, users)
|
config.auth = InitAuth(fn, users, 60)
|
||||||
|
|
||||||
handlerCalled := false
|
handlerCalled := false
|
||||||
handler := func(w http.ResponseWriter, r *http.Request) {
|
handler := func(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -129,7 +129,7 @@ func TestAuthHTTP(t *testing.T) {
|
|||||||
assert.True(t, handlerCalled)
|
assert.True(t, handlerCalled)
|
||||||
|
|
||||||
// perform login
|
// perform login
|
||||||
cookie := httpCookie(loginJSON{Name: "name", Password: "password"})
|
cookie := config.auth.httpCookie(loginJSON{Name: "name", Password: "password"})
|
||||||
assert.True(t, cookie != "")
|
assert.True(t, cookie != "")
|
||||||
|
|
||||||
// get /
|
// get /
|
||||||
|
@ -91,6 +91,10 @@ type configuration struct {
|
|||||||
Language string `yaml:"language"` // two-letter ISO 639-1 language code
|
Language string `yaml:"language"` // two-letter ISO 639-1 language code
|
||||||
RlimitNoFile uint `yaml:"rlimit_nofile"` // Maximum number of opened fd's per process (0: default)
|
RlimitNoFile uint `yaml:"rlimit_nofile"` // Maximum number of opened fd's per process (0: default)
|
||||||
|
|
||||||
|
// TTL for a web session (in hours)
|
||||||
|
// An active session is automatically refreshed once a day.
|
||||||
|
WebSessionTTLHours uint32 `yaml:"web_session_ttl"`
|
||||||
|
|
||||||
DNS dnsConfig `yaml:"dns"`
|
DNS dnsConfig `yaml:"dns"`
|
||||||
TLS tlsConfig `yaml:"tls"`
|
TLS tlsConfig `yaml:"tls"`
|
||||||
Filters []filter `yaml:"filters"`
|
Filters []filter `yaml:"filters"`
|
||||||
@ -210,6 +214,8 @@ func initConfig() {
|
|||||||
Transport: config.transport,
|
Transport: config.transport,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
config.WebSessionTTLHours = 30 * 24
|
||||||
|
|
||||||
if runtime.GOARCH == "mips" || runtime.GOARCH == "mipsle" {
|
if runtime.GOARCH == "mips" || runtime.GOARCH == "mipsle" {
|
||||||
// Use plain DNS on MIPS, encryption is too slow
|
// Use plain DNS on MIPS, encryption is too slow
|
||||||
defaultDNS = []string{"1.1.1.1", "1.0.0.1"}
|
defaultDNS = []string{"1.1.1.1", "1.0.0.1"}
|
||||||
|
@ -68,7 +68,7 @@ func initDNSServer() {
|
|||||||
config.dnsServer = dnsforward.NewServer(config.dnsFilter, config.stats, config.queryLog)
|
config.dnsServer = dnsforward.NewServer(config.dnsFilter, config.stats, config.queryLog)
|
||||||
|
|
||||||
sessFilename := filepath.Join(baseDir, "sessions.db")
|
sessFilename := filepath.Join(baseDir, "sessions.db")
|
||||||
config.auth = InitAuth(sessFilename, config.Users)
|
config.auth = InitAuth(sessFilename, config.Users, config.WebSessionTTLHours*60*60)
|
||||||
config.Users = nil
|
config.Users = nil
|
||||||
|
|
||||||
config.dnsctx.rdns = InitRDNS(&config.clients)
|
config.dnsctx.rdns = InitRDNS(&config.clients)
|
||||||
|
Loading…
Reference in New Issue
Block a user