所使用的中间件有 yaag,jwt,casbin,logger
app := iris.New()
app.Logger().SetLevel("debug")
//初始化中间件,API文档
yaag.Init(&yaag.Config{
On: true, //是否开启自动生成API文档功能
DocTitle: "Iris",
DocPath: "./api/apidoc.html", //生成API文档名称存放路径
BaseUrls: map[string]string{"Production": "", "Staging": ""},
})
// 初始化中间件,xorm 引擎
configs.MysqlEngine()
// 请求日志记录
customLogger := logger.New(logger.Config{
//状态显示状态代码
Status: true,
// IP显示请求的远程地址
IP: true,
//方法显示http方法
Method: true,
// Path显示请求路径
Path: true,
// Query将url查询附加到Path。
Query: true,
//Columns:true,
// 如果不为空然后它的内容来自`ctx.Values(),Get("logger_message")
//将添加到日志中。
MessageContextKeys: []string{"logger_message"},
//如果不为空然后它的内容来自`ctx.GetHeader(“User-Agent”)
MessageHeaderKeys: []string{"User-Agent"},
})
app.Use(customLogger)
//加载模板文件
app.RegisterView(iris.HTML("./web/views/", ".html"))
//加载静态资源
app.HandleDir("/", "./web/static")
// 添加路由
routers.Routers(app)
app.Run(
//开启web服务
iris.Addr("localhost:8080"),
//实现更快的json序列化和更多优化
iris.WithOptimizations,
iris.WithCharset("utf-8"),
)
我这里为了方便,并没有重构代码,可以一次性将代码展示出来,可以看到 写出以下功能:
func Routers(api *iris.Application){
app := api.Party("/", middleware.CrsAuth()).AllowMethods(iris.MethodOptions)
{
app.Get("/", func(ctx iris.Context) { // 首页模块
_ = ctx.View("login.html")
})
back := app.Party("/back")
{
back.HandleDir("/", "./web/static")
back.Post("/doAJAXLogin",controllers.DoAJAXLogin).Name = "登录"
//back.Use(irisyaag.New())
casbin := middleware.InitCasbin()
casbinMiddleware := middleware.New(casbin) //casbin for xorm
back.Use(middleware.JWTMiddleware().Serve,casbinMiddleware.ServeHTTP) //登录验证
back.Get("/logout",controllers.Logout).Name = "退出"
back.Get("/main",controllers.Main).Name = "back 主页"
back.PartyFunc("/user", func(p router.Party) {
//后台之 user管理
p.Post("/deletes",controllers.Deletes).Name = "user deletes"
p.Post("/delete",controllers.Delete).Name = "user delete"
p.Post("/update",controllers.Update).Name = "user update"
p.Get("/edit",controllers.Edit).Name = "user edit"
p.Get("/assign",controllers.Assign).Name = ""
p.Post("/doAssign",controllers.DoAssign).Name = ""
p.Post("/dounAssign",controllers.DounAssign).Name = ""
p.Post("/insert",controllers.Insert).Name = ""
p.Post("/add",controllers.Add).Name = ""
p.Post("/pageQuery",controllers.PageQuery).Name = ""
p.Post("/Index",controllers.Index).Name = ""
p.Post("/Index1",controllers.Index1).Name = ""
})
}
}
}
在上一文章中说到iris没有采用mvc的模式,所有路由这里都是采用方法 当做 handle,通过party 来进行分组。
需要特别注意的是: 加入的权限管理中间件的加载
casbin := middleware.InitCasbin()
casbinMiddleware := middleware.New(casbin) //casbin for xorm
back.Use(middleware.JWTMiddleware().Serve,casbinMiddleware.ServeHTTP) //登录验证
在那个party下加载,那么这个party 下的所有请求,都会受到权限验证的操作。
var (
loginAcct = ctx.FormValue("loginAcct")
password = ctx.FormValue("userPsWd")
)
loginers:= models.User{
LoginAcct: loginAcct,
UserPsWd: password,
}
login, err := dao.QueryLogin(&loginers)
if err != nil{
ctx.JSON(models.AJAXResult{
Success: false,
Msg: "error",
})
return
}
if login.Id == 0 {
ctx.JSON( models.AJAXResult{
Success: false,
})
return
} else {
// 账号密码正确,得到用户
token := jwt.NewTokenWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"exp": time.Now().Add(time.Hour * time.Duration(1)).Unix(),
"iat": time.Now().Unix(),
})
tokenString, _ := token.SignedString([]byte("HS2JDFKhu7Y1av7b"))
oauthToken := new(dao.OauthToken)
oauthToken.Token = tokenString
oauthToken.UserId = login.Id
oauthToken.Secret = "secret"
oauthToken.Revoked = false
oauthToken.ExpressIn = time.Now().Add(time.Hour * time.Duration(1)).Unix()
response := oauthToken.OauthTokenCreate()
ctx.JSON(models.AJAXResult{
Success: true,
Data: response,
})
return
在整个代码代码中,因为我比较懒,没有写service 模式,直接调用dao 中的方法,但是有个区别就是jwt是采用的结构体的方法-----相当于每一个用户都会创建一个oauthToken 的结构体实例,调用结构体中方法,去验证token 和创建token保存到数据库中。
userId, _ := strconv.Atoi(ctx.FormValue("userId"))
ot := dao.OauthToken{}
ot.UpdateOauthTokenByUserId(userId)
ctx.JSON(models.AJAXResult{
Success: true,
Msg: "user exit",
})
当退出,调用dao中的方法,删除数据库保存的token
通过查看手册,可以看到基本的操作逻辑和实现的方法,直接贴代码
func InitCasbin() *casbin.Enforcer {
a, _ := xormadapter.NewAdapterByEngine(configs.Engine)
e, _ := casbin.NewEnforcer("./rbac_model.conf", a)
_ = e.LoadPolicy()
// Check the permission.
// Modify the policy.
// e.AddPolicy(...)
// e.RemovePolicy(...)
// Save the policy back to DB.
e.SavePolicy()
return e
}
func New(e *casbin.Enforcer) *Casbin {
return &Casbin{enforcer: e}
}
// 判断token
func (c *Casbin) ServeHTTP(ctx context.Context) {
value := ctx.Values().Get("jwt").(*jwt.Token)
token := dao.OauthToken{}
token.GetOauthTokenByToken(value.Raw) //获取 access_token 信息
if token.Revoked || token.ExpressIn < time.Now().Unix() {
//无权限
ctx.StopExecution()
return
} else if !c.Check(ctx.Request(), strconv.FormatUint(uint64(token.UserId), 10)) {
// Status Forbidden
ctx.StopExecution()
return
} else {
ctx.Values().Set("auth_user_id", token.UserId)
}
ctx.Next()
}
// Casbin is the auth services which contains the casbin enforcer.
type Casbin struct {
enforcer *casbin.Enforcer
}
// Check checks the username, request's method and path and
// returns true if permission grandted otherwise false.
func (c *Casbin) Check(r *http.Request, userId string) bool {
method := r.Method
path := r.URL.Path
ok, _ := c.enforcer.Enforce(userId, path, method)
return ok
}
一定注意导入的依赖 是一致性的
例如iris,就存在两个版本,一个github一个xorm官网。
其他中间件也分为 v2 等两个版本,相互之间,版本依赖不是互通的。