token based anti-spam for when javascript is disabled

reduce the number of allocs when generating templates
This commit is contained in:
Azareal 2020-06-19 16:38:32 +10:00
parent 195b41cb79
commit 572ff8e073
4 changed files with 78 additions and 26 deletions

View File

@ -246,6 +246,12 @@ type IPSearchPage struct {
IP string IP string
} }
type RegisterPage struct {
*Header
RequireEmail bool
Token string
}
type Account struct { type Account struct {
*Header *Header
HTMLID string HTMLID string

View File

@ -349,7 +349,7 @@ func compileTemplates(wg *sync.WaitGroup, c *tmpl.CTemplateSet, themeName string
} }
t.AddStd("login", "c.Page", Page{htitle("Login Page"), tList, nil}) t.AddStd("login", "c.Page", Page{htitle("Login Page"), tList, nil})
t.AddStd("register", "c.Page", Page{htitle("Registration Page"), tList, false}) t.AddStd("register", "c.RegisterPage", RegisterPage{htitle("Registration Page"), false,""})
t.AddStd("error", "c.ErrorPage", ErrorPage{htitle("Error"), "A problem has occurred in the system."}) t.AddStd("error", "c.ErrorPage", ErrorPage{htitle("Error"), "A problem has occurred in the system."})
ipSearchPage := IPSearchPage{htitle("IP Search"), map[int]*User{1: user2}, "::1"} ipSearchPage := IPSearchPage{htitle("IP Search"), map[int]*User{1: user2}, "::1"}
@ -625,6 +625,7 @@ func getTemplateList(c *tmpl.CTemplateSet, wg *sync.WaitGroup, prefix string) st
bodyMap := make(map[string]string) //map[body]fragmentPrefix bodyMap := make(map[string]string) //map[body]fragmentPrefix
//tmplMap := make(map[string]map[string]string) // map[tmpl]map[body]fragmentPrefix //tmplMap := make(map[string]map[string]string) // map[tmpl]map[body]fragmentPrefix
tmpCount := 0 tmpCount := 0
var bsb strings.Builder
for _, frag := range c.FragOut { for _, frag := range c.FragOut {
front := frag.TmplName + "_frags[" + strconv.Itoa(frag.Index) + "]" front := frag.TmplName + "_frags[" + strconv.Itoa(frag.Index) + "]"
DebugLog("front: ", front) DebugLog("front: ", front)
@ -637,25 +638,32 @@ func getTemplateList(c *tmpl.CTemplateSet, wg *sync.WaitGroup, prefix string) st
fp, ok := bodyMap[frag.Body] fp, ok := bodyMap[frag.Body]
if !ok { if !ok {
bodyMap[frag.Body] = front bodyMap[frag.Body] = front
var bits string //var bits string
bsb.Reset()
DebugLog("encoding f.Body") DebugLog("encoding f.Body")
for _, char := range []byte(frag.Body) { for _, char := range []byte(frag.Body) {
if char == '\'' { if char == '\'' {
bits += "'\\" + string(char) + "'," //bits += "'\\" + string(char) + "',"
bsb.WriteString("'\\'',")
} else if char < 32 { } else if char < 32 {
bits += strconv.Itoa(int(char)) + "," //bits += strconv.Itoa(int(char)) + ","
bsb.WriteString(strconv.Itoa(int(char)))
bsb.WriteByte(',')
} else { } else {
bits += "'" + string(char) + "'," //bits += "'" + string(char) + "',"
bsb.WriteByte('\'')
bsb.WriteString(string(char))
bsb.WriteString("',")
} }
} }
tmpStr := strconv.Itoa(tmpCount) tmpStr := strconv.Itoa(tmpCount)
pout += "arr_" + tmpStr + " := [...]byte{" + bits + "}\n" pout += "arr_" + tmpStr + ":=[...]byte{" + /*bits*/ bsb.String() + "}\n"
pout += front + " = arr_" + tmpStr + "[:]\n" pout += front + "=arr_" + tmpStr + "[:]\n"
tmpCount++ tmpCount++
//pout += front + " = []byte(`" + frag.Body + "`)\n" //pout += front + "=[]byte(`" + frag.Body + "`)\n"
} else { } else {
DebugLog("encoding cached index " + fp) DebugLog("encoding cached index " + fp)
pout += front + " = " + fp + "\n" pout += front + "=" + fp + "\n"
} }
_, ok = tFragCount[frag.TmplName] _, ok = tFragCount[frag.TmplName]
@ -665,21 +673,43 @@ func getTemplateList(c *tmpl.CTemplateSet, wg *sync.WaitGroup, prefix string) st
tFragCount[frag.TmplName]++ tFragCount[frag.TmplName]++
} }
out := "package " + c.GetConfig().PackageName + "\n\n" //out := "package " + c.GetConfig().PackageName + "\n\n"
getterstr := "\n// nolint\nGetFrag = func(name string) [][]byte {\nswitch(name) {\n" var sb strings.Builder
sb.Grow(tllenhint)
sb.WriteString("package ")
sb.WriteString(c.GetConfig().PackageName)
sb.WriteString("\n\n")
for templateName, count := range tFragCount { for templateName, count := range tFragCount {
//out += "var " + templateName + "_frags = make([][]byte," + strconv.Itoa(count) + ")\n" //out += "var " + templateName + "_frags = make([][]byte," + strconv.Itoa(count) + ")\n"
out += "var " + templateName + "_frags [" + strconv.Itoa(count) + "][]byte\n" //out += "var " + templateName + "_frags [" + strconv.Itoa(count) + "][]byte\n"
getterstr += "\tcase \"" + templateName + "\":\n" sb.WriteString("var ")
//getterstr += "\treturn " + templateName + "_frags\n" sb.WriteString(templateName)
getterstr += "\treturn " + templateName + "_frags[:]\n" sb.WriteString("_frags [")
sb.WriteString(strconv.Itoa(count))
sb.WriteString("][]byte\n")
} }
getterstr += "}\nreturn nil\n}\n" sb.WriteString(pout)
out += pout + "\n" + getterstr + "}\n" sb.WriteString("\n\n// nolint\nGetFrag = func(name string) [][]byte {\nswitch(name) {\n")
//getterstr := "\n// nolint\nGetFrag = func(name string) [][]byte {\nswitch(name) {\n"
for templateName, _ := range tFragCount {
//getterstr += "\tcase \"" + templateName + "\":\n"
///getterstr += "\treturn " + templateName + "_frags\n"
//getterstr += "\treturn " + templateName + "_frags[:]\n"
sb.WriteString("\tcase \"")
sb.WriteString(templateName)
sb.WriteString("\":\n\treturn ")
sb.WriteString(templateName)
sb.WriteString("_frags[:]\n")
}
sb.WriteString("}\nreturn nil\n}\n}\n")
//getterstr += "}\nreturn nil\n}\n"
//out += pout + "\n" + getterstr + "}\n"
return out return sb.String()
} }
var tllenhint = len("package \n\n\n// nolint\nGetFrag = func(name string) [][]byte {\nswitch(name) {\nvar _frags [][]byte\n\tcase \"\":\n\treturn _frags[:]\n}\nreturn nil\n}\n\n}\n")
func writeTemplateList(c *tmpl.CTemplateSet, wg *sync.WaitGroup, prefix string) { func writeTemplateList(c *tmpl.CTemplateSet, wg *sync.WaitGroup, prefix string) {
log.Print("Writing template list") log.Print("Writing template list")
wg.Add(1) wg.Add(1)

View File

@ -191,7 +191,16 @@ func AccountRegister(w http.ResponseWriter, r *http.Request, u *c.User, h *c.Hea
} }
h.Title = p.GetTitlePhrase("register") h.Title = p.GetTitlePhrase("register")
h.AddScriptAsync("register.js") h.AddScriptAsync("register.js")
return renderTemplate("register", w, r, h, c.Page{h, tList, h.Settings["activation_type"] != 2})
var token string
if c.Config.DisableJSAntispam {
h := sha256.New()
h.Write([]byte(c.JSTokenBox.Load().(string)))
h.Write([]byte(u.GetIP()))
token = hex.EncodeToString(h.Sum(nil))
}
return renderTemplate("register", w, r, h, c.RegisterPage{h, h.Settings["activation_type"] != 2, token})
} }
func isNumeric(data string) (numeric bool) { func isNumeric(data string) (numeric bool) {
@ -221,13 +230,20 @@ func AccountRegisterSubmit(w http.ResponseWriter, r *http.Request, user *c.User)
if r.PostFormValue("tos") != "0" { if r.PostFormValue("tos") != "0" {
regError(p.GetErrorPhrase("register_might_be_machine"), "trap-question") regError(p.GetErrorPhrase("register_might_be_machine"), "trap-question")
} }
if !c.Config.DisableJSAntispam {
{
h := sha256.New() h := sha256.New()
h.Write([]byte(c.JSTokenBox.Load().(string))) h.Write([]byte(c.JSTokenBox.Load().(string)))
h.Write([]byte(user.GetIP())) h.Write([]byte(user.GetIP()))
if !c.Config.DisableJSAntispam {
if r.PostFormValue("golden-watch") != hex.EncodeToString(h.Sum(nil)) { if r.PostFormValue("golden-watch") != hex.EncodeToString(h.Sum(nil)) {
regError(p.GetErrorPhrase("register_might_be_machine"), "js-antispam") regError(p.GetErrorPhrase("register_might_be_machine"), "js-antispam")
} }
} else {
if r.PostFormValue("areg") != hex.EncodeToString(h.Sum(nil)) {
regError(p.GetErrorPhrase("register_might_be_machine"), "token")
}
}
} }
name := c.SanitiseSingleLine(r.PostFormValue("name")) name := c.SanitiseSingleLine(r.PostFormValue("name"))

View File

@ -10,8 +10,8 @@
<div class="formitem"><input name="name"type="text"placeholder="{{lang "register_account_name"}}"aria-labelledby="name_label"required></div> <div class="formitem"><input name="name"type="text"placeholder="{{lang "register_account_name"}}"aria-labelledby="name_label"required></div>
</div> </div>
<div class="formrow"> <div class="formrow">
<div class="formitem formlabel"><a id="email_label">{{if not .Something}}{{lang "register_account_email"}}{{else}}{{lang "register_account_email_optional"}}{{end}}</a></div> <div class="formitem formlabel"><a id="email_label">{{if not .RequireEmail}}{{lang "register_account_email"}}{{else}}{{lang "register_account_email_optional"}}{{end}}</a></div>
<div class="formitem"><input name="email"type="email"placeholder="joe.doe@example.com"aria-labelledby="email_label"{{if not .Something}}required{{end}}></div> <div class="formitem"><input name="email"type="email"placeholder="joe.doe@example.com"aria-labelledby="email_label"{{if not .RequireEmail}}required{{end}}></div>
</div> </div>
<div class="formrow"> <div class="formrow">
<div class="formitem formlabel"><a id="password_label">{{lang "register_account_password"}}</a></div> <div class="formitem formlabel"><a id="password_label">{{lang "register_account_password"}}</a></div>
@ -31,7 +31,7 @@
<div class="formrow register_button_row form_button_row"> <div class="formrow register_button_row form_button_row">
<div class="formitem"><button name="register-button"class="formbutton">{{lang "register_submit_button"}}</button></div> <div class="formitem"><button name="register-button"class="formbutton">{{lang "register_submit_button"}}</button></div>
</div> </div>
<input id="golden-watch"name="golden-watch"value="$500"type="hidden"> {{if eq .Token ""}}<input id="golden-watch"name="golden-watch"value="$500"type="hidden">{{else}}<input id="areg"name="areg"value="{{.Token}}"type="hidden">{{end}}
</form> </form>
</div> </div>
</main> </main>