added login referer
This commit is contained in:
parent
2e70a95bcd
commit
4e5d554105
7 changed files with 55 additions and 15 deletions
|
|
@ -9,5 +9,6 @@ const (
|
|||
IndexURI = WikiSection + "/" + IndexPage
|
||||
|
||||
LoginURI = "/login"
|
||||
LogoutURI = "/logout"
|
||||
TotpURI = "/totp"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
"github.com/gorilla/mux"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
)
|
||||
|
||||
|
|
@ -23,6 +24,7 @@ const (
|
|||
titleClaim = "title"
|
||||
totpClaim = "totp"
|
||||
rememberClaim = "remember"
|
||||
refererClaim = "referer"
|
||||
)
|
||||
|
||||
func newContext(w http.ResponseWriter, r *http.Request, s *HTTPServer) (ctx *Context) {
|
||||
|
|
@ -30,7 +32,8 @@ func newContext(w http.ResponseWriter, r *http.Request, s *HTTPServer) (ctx *Con
|
|||
h.Set("X-Frame-Options", "DENY")
|
||||
h.Set("X-Content-Type-Options", "nosniff")
|
||||
h.Set("X-XSS-Protection", "1; mode=block")
|
||||
h.Set("Content-Security-Policy", "default-src 'none';style-src 'self';img-src 'self' data:;frame-ancestors 'none'")
|
||||
h.Set("Content-Security-Policy", "default-src 'none';style-src 'self';img-src 'self' https: data:;connect-src 'self';frame-ancestors 'none'")
|
||||
h.Set("Referrer-Policy", "same-origin")
|
||||
ctx = &Context{
|
||||
Request: r,
|
||||
Response: w,
|
||||
|
|
@ -53,7 +56,7 @@ func newContext(w http.ResponseWriter, r *http.Request, s *HTTPServer) (ctx *Con
|
|||
return
|
||||
}
|
||||
if t.Claims.GetString(totpClaim) != "" {
|
||||
if path == core.TotpURI || path == core.LoginURI {
|
||||
if path == core.TotpURI || path == core.LoginURI || path == core.LogoutURI {
|
||||
ctx.Token = *t
|
||||
return
|
||||
}
|
||||
|
|
@ -107,6 +110,11 @@ type webData struct {
|
|||
Data interface{}
|
||||
}
|
||||
|
||||
type loginData struct {
|
||||
User string
|
||||
Referer string
|
||||
}
|
||||
|
||||
func (c *Context) Exec() {
|
||||
defer c.log()
|
||||
if c.T == nil {
|
||||
|
|
@ -201,6 +209,14 @@ func (c *Context) Path() string {
|
|||
return c.Request.URL.Path
|
||||
}
|
||||
|
||||
func (c *Context) RefererURI() string {
|
||||
u, err := url.Parse(c.Request.Header.Get("Referer"))
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return u.RequestURI()
|
||||
}
|
||||
|
||||
func (c *Context) FormSlice(name string) []string {
|
||||
// does nothing if called twice
|
||||
c.Request.ParseForm()
|
||||
|
|
@ -286,6 +302,10 @@ func (c *Context) Remember() string {
|
|||
return c.Token.Claims.GetString(rememberClaim)
|
||||
}
|
||||
|
||||
func (c *Context) Referer() string {
|
||||
return c.Token.Claims.GetString(refererClaim)
|
||||
}
|
||||
|
||||
func (c *Context) Admin() bool {
|
||||
return c.Token.Claims.GetBool(adminClaim)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,23 +93,28 @@ func loginHandler(ctx *Context) {
|
|||
Title: "Login",
|
||||
BodyTitle: "Login",
|
||||
}
|
||||
var user string
|
||||
var data loginData
|
||||
switch ctx.Method() {
|
||||
case "GET":
|
||||
ctx.Data.Data = user
|
||||
data.Referer = ctx.RefererURI()
|
||||
ctx.Data.Data = data
|
||||
ctx.Exec()
|
||||
case "POST":
|
||||
if !ctx.CheckXsrf() {
|
||||
return
|
||||
}
|
||||
user = ctx.Form("user")
|
||||
ctx.Data.Data = user
|
||||
data.User = ctx.Form("user")
|
||||
data.Referer = ctx.Form("referer")
|
||||
ctx.Data.Data = data
|
||||
if data.Referer == "" {
|
||||
data.Referer = core.IndexURI
|
||||
}
|
||||
password := ctx.Form("password")
|
||||
if user == "" || password == "" {
|
||||
if data.User == "" || password == "" {
|
||||
ctx.Error("empty user or password")
|
||||
return
|
||||
}
|
||||
u, err := ctx.Srv.DB.Login(user, password)
|
||||
u, err := ctx.Srv.DB.Login(data.User, password)
|
||||
if err != nil {
|
||||
ctx.Error(err)
|
||||
return
|
||||
|
|
@ -117,12 +122,13 @@ func loginHandler(ctx *Context) {
|
|||
if u.Secret == "" {
|
||||
log.Println("login:", u.Username)
|
||||
ctx.Login(u, ctx.Form("remember"))
|
||||
ctx.Redirect(core.IndexURI, http.StatusFound)
|
||||
ctx.Redirect(data.Referer, http.StatusFound)
|
||||
return
|
||||
}
|
||||
ctx.SetCookie(jwt.Claims{
|
||||
totpClaim: u.Username,
|
||||
rememberClaim: ctx.Form("remember"),
|
||||
refererClaim: data.Referer,
|
||||
}, time.Minute)
|
||||
ctx.Redirect(core.TotpURI, http.StatusFound)
|
||||
}
|
||||
|
|
@ -155,9 +161,10 @@ func loginTotpHandler(ctx *Context) {
|
|||
ctx.Error(err)
|
||||
return
|
||||
}
|
||||
ref := ctx.Referer()
|
||||
log.Println("login:", u.Username)
|
||||
ctx.Login(u, ctx.Remember())
|
||||
ctx.Redirect(core.IndexURI, http.StatusFound)
|
||||
ctx.Redirect(ref, http.StatusFound)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -682,7 +689,11 @@ func userDelHandler(ctx *Context) {
|
|||
}
|
||||
|
||||
func logoutHandler(ctx *Context) {
|
||||
log.Println("logout:", ctx.User())
|
||||
user := ctx.User()
|
||||
if user == "" {
|
||||
user = ctx.Totp() + " (totp)"
|
||||
}
|
||||
log.Println("logout:", user)
|
||||
ctx.Srv.JWT.Invalidate(&ctx.Token)
|
||||
ctx.SetCookie(nil, 0)
|
||||
ctx.Redirect(core.IndexURI, http.StatusFound)
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ const (
|
|||
<title>GoWiki | {{.Title}}</title>
|
||||
<link rel="stylesheet" type="text/css" href="/bootstrap.css" media="screen" integrity="sha256-NeLmQ7cX66J4MdtgGlG3O/TgvsSyP1b9WbaQtxYZUbQ="></link>
|
||||
<link rel="stylesheet" type="text/css" href="/custom.css" media="screen" integrity="sha256-/SZfW8eVqFuioMg+QXacvK1Zc3XLtT5LGu9tMle65Jc="></link>
|
||||
<meta name="theme-color" content="#375a7f">
|
||||
<meta name="description" content="{{.Title}}">
|
||||
</head>
|
||||
<body id="top">
|
||||
<div class="navbar navbar-expand fixed-top navbar-dark bg-primary">
|
||||
|
|
@ -114,9 +116,10 @@ const (
|
|||
<div class="card-body">
|
||||
<form class="form-horizontal" action="/login" method="post">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<input type="hidden" name="referer" value="{{.Data.Referer}}">
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="user">Username</label>
|
||||
<input class="form-control input-sm" type="text" id="user" name="user" value="{{.Data}}" autofocus required>
|
||||
<input class="form-control input-sm" type="text" id="user" name="user" value="{{.Data.User}}" autofocus required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="password">Password</label>
|
||||
|
|
@ -152,6 +155,7 @@ const (
|
|||
<input class="form-control input-sm" type="text" id="pin" name="pin" autocomplete="off" autofocus required>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-primary" type="submit">Verify</button>
|
||||
<a href="/logout" class="btn btn-sm btn-primary">Cancel</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
<title>GoWiki | {{.Title}}</title>
|
||||
<link rel="stylesheet" type="text/css" href="/bootstrap.css" media="screen" integrity="sha256-NeLmQ7cX66J4MdtgGlG3O/TgvsSyP1b9WbaQtxYZUbQ="></link>
|
||||
<link rel="stylesheet" type="text/css" href="/custom.css" media="screen" integrity="sha256-/SZfW8eVqFuioMg+QXacvK1Zc3XLtT5LGu9tMle65Jc="></link>
|
||||
<meta name="theme-color" content="#375a7f">
|
||||
<meta name="description" content="{{.Title}}">
|
||||
</head>
|
||||
<body id="top">
|
||||
<div class="navbar navbar-expand fixed-top navbar-dark bg-primary">
|
||||
|
|
|
|||
|
|
@ -9,9 +9,10 @@
|
|||
<div class="card-body">
|
||||
<form class="form-horizontal" action="/login" method="post">
|
||||
<input type="hidden" name="token" value="{{.Token}}">
|
||||
<input type="hidden" name="referer" value="{{.Data.Referer}}">
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="user">Username</label>
|
||||
<input class="form-control input-sm" type="text" id="user" name="user" value="{{.Data}}" autofocus required>
|
||||
<input class="form-control input-sm" type="text" id="user" name="user" value="{{.Data.User}}" autofocus required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="col-form-label" for="password">Password</label>
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
<input class="form-control input-sm" type="text" id="pin" name="pin" autocomplete="off" autofocus required>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-primary" type="submit">Verify</button>
|
||||
<a href="/logout" class="btn btn-sm btn-primary">Cancel</a>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue