// CsrfFilter enables CSRF request token creation and verification. // // Usage: // 1) Add `csrf.CsrfFilter` to the app's filters (it must come after the revel.SessionFilter). // 2) Add CSRF fields to a form with the template tag `{{ csrftoken . }}`. The filter adds a function closure to the `RenderArgs` that can pull out the secret and make the token as-needed, caching the value in the request. Ajax support provided through the `X-CSRFToken` header. func CsrfFilter(c *revel.Controller, fc []revel.Filter) { token, foundToken := c.Session["csrf_token"] if !foundToken { RefreshToken(c) } referer, refErr := url.Parse(c.Request.Header.Get("Referer")) isSameOrigin := sameOrigin(c.Request.URL, referer) // If the Request method isn't in the white listed methods if !allowedMethods[c.Request.Method] && !IsExempt(c) { // Token wasn't present at all if !foundToken { c.Result = c.Forbidden("REVEL CSRF: Session token missing.") return } // Referer header is invalid if refErr != nil { c.Result = c.Forbidden("REVEL CSRF: HTTP Referer malformed.") return } // Same origin if !isSameOrigin { c.Result = c.Forbidden("REVEL CSRF: Same origin mismatch.") return } var requestToken string // First check for token in post data if c.Request.Method == "POST" { requestToken = c.Request.FormValue("csrftoken") } // Then check for token in custom headers, as with AJAX if requestToken == "" { requestToken = c.Request.Header.Get("X-CSRFToken") } if requestToken == "" || !compareToken(requestToken, token) { c.Result = c.Forbidden("REVEL CSRF: Invalid token.") return } } fc[0](c, fc[1:]) // Only add token to RenderArgs if the request is: not AJAX, not missing referer header, and is same origin. if c.Request.Header.Get("X-CSRFToken") == "" && isSameOrigin { c.RenderArgs["_csrftoken"] = token } }
/* Filter AuthFilter is Revel Filter for JWT Auth Token verification Register it in the revel.Filters in <APP_PATH>/app/init.go Add jwt.AuthFilter anywhere deemed appropriate, it must be register after revel.PanicFilter revel.Filters = []revel.Filter{ revel.PanicFilter, ... jwt.AuthFilter, // JWT Auth Token verification for Request Paths ... } Note: If everything looks good then Claims map made available via c.Args and can be accessed using c.Args[jwt.TOKEN_CLAIMS_KEY] */ func AuthFilter(c *revel.Controller, fc []revel.Filter) { if !anonymousPaths.MatchString(c.Request.URL.Path) { token, err := ParseFromRequest(c.Request.Request) if err == nil && token.Valid && !IsInBlocklist(GetAuthToken(c.Request)) { c.Args[TOKEN_CLAIMS_KEY] = token.Claims fc[0](c, fc[1:]) // everything looks good, move on } else { if ve, ok := err.(*jwt.ValidationError); ok { if ve.Errors&jwt.ValidationErrorMalformed != 0 { revel.ERROR.Println("That's not even a token") } else if ve.Errors&(jwt.ValidationErrorExpired|jwt.ValidationErrorNotValidYet) != 0 { revel.ERROR.Println("Timing is everything, Token is either expired or not active yet") } else { revel.ERROR.Printf("Couldn't handle this token: %v", err) } } else { revel.ERROR.Printf("Couldn't handle this token: %v", err) } c.Response.Status = http.StatusUnauthorized c.Response.Out.Header().Add("WWW-Authenticate", Realm) c.Result = c.RenderJson(map[string]string{ "id": "unauthorized", "message": "Invalid or token is not provided", }) return } } fc[0](c, fc[1:]) //not applying JWT auth filter due to anonymous path }
func ServeStatic(uri, contentType string, c *revel.Controller) { filePath := GetFilePath(uri) revel.INFO.Printf("read static file %s\n", filePath) file, err := os.Open(filePath) defer file.Close() if err != nil { c.Result = CommonResult{Data: []byte(`sorry file not found`)} return } data, err := ioutil.ReadAll(file) if err != nil { c.Result = CommonResult{Data: []byte(`sorry file not found`)} return } c.Result = CommonResult{Data: data, ContentType: contentType} }
func RouterFilter(c *revel.Controller, fc []revel.Filter) { // 补全controller部分 path := c.Request.Request.URL.Path // Figure out the Controller/Action var route *revel.RouteMatch = revel.MainRouter.Route(c.Request.Request) if route == nil { c.Result = c.NotFound("No matching route found: " + c.Request.RequestURI) return } // The route may want to explicitly return a 404. if route.Action == "404" { c.Result = c.NotFound("(intentionally)") return } //---------- // life start /* type URL struct { Scheme string Opaque string // encoded opaque data User *Userinfo // username and password information Host string // host or host:port Path string RawQuery string // encoded query values, without '?' Fragment string // fragment for references, without '#' } */ if route.ControllerName != "Static" { // api设置 // leanote.com/api/user/get => ApiUser::Get //* /api/login ApiAuth.Login, 这里的设置, 其实已经转成了ApiAuth了 if strings.HasPrefix(path, "/api") && !strings.HasPrefix(route.ControllerName, "Api") { route.ControllerName = "Api" + route.ControllerName } else if strings.HasPrefix(path, "/member") && !strings.HasPrefix(route.ControllerName, "Member") { // member设置 route.ControllerName = "Member" + route.ControllerName } // end } // Set the action. if err := c.SetAction(route.ControllerName, route.MethodName); err != nil { c.Result = c.NotFound(err.Error()) return } // Add the route and fixed params to the Request Params. c.Params.Route = route.Params // Add the fixed parameters mapped by name. // TODO: Pre-calculate this mapping. for i, value := range route.FixedParams { if c.Params.Fixed == nil { c.Params.Fixed = make(url.Values) } if i < len(c.MethodType.Args) { arg := c.MethodType.Args[i] c.Params.Fixed.Set(arg.Name, value) } else { revel.WARN.Println("Too many parameters to", route.Action, "trying to add", value) break } } fc[0](c, fc[1:]) }
// scss 样式 func ServeSCSS(uri string, c *revel.Controller) { filePath := GetFilePath(uri) data := findInCache(filePath, buildScss) c.Result = CommonResult{Data: data, ContentType: ContentTypeCSS} }
func ServeCoffee(uri string, c *revel.Controller) { filePath := GetFilePath(uri) data := findInCache(filePath, buildCoffee) c.Result = CommonResult{Data: data, ContentType: ContentTypeJS} }