This is the 25th day of my participation in the More text Challenge. For more details, see more text Challenge

GO Permission management Casbin

Let’s review the application and sharing of the GJSON library in GO, which provides a very fast and easy way to get values from JSON documents

  • To share thejsonwithgjsonWhat does that mean?
  • gjsonSimple use of
  • gjsonCheck to get the value
  • gjsontheJson line
  • gjsonIs the key path matching rule
  • gjsonAnd custom modifiers

If you’re still interested in gJSON, check out the GO article for gJSON application and sharing

Today let’s share the permission management in GO, Casbin

What is permission management?

Generally, it refers to the security rules or policies set according to the system

Users can access only the resources they are authorized to, no more, no less, just right

Rights management can be found in almost any system

We may confuse user authentication, password encryption, and system administration with rights management, but what are their specific priorities?

  • User Identity authentication

Does not belong to the scope of rights management

User identity authentication refers to the use of some kind of credentials to prove their identity, such as account password, fingerprint, face recognition, and so on

  • System management

Is a module in the system, which generally contains a submodule of permission management, which is equivalent to providing some data to the permission management module

  • Password encryption

It does not belong to the domain of rights management, it is only a part of the domain of user identity authentication

What is a Casbin?

Casbin is a powerful and efficient open source access control library for GO projects. Casbin supports a variety of commonly used access control models, such as:

  • RBAC
  • ABAC
  • ACL

The nice thing about using Casbin for permission management is that casbin supports multiple languages, just like Protobuf does

Let’s take a look at what Casbin has

  • The implementation strategy looks like this{subject, object, action}.

We can also customize it, and it supports allowing authorization and denying authorization

  • It can handle the access control model and the policies corresponding to its storage
  • inRBACIn the role hierarchy, he can manage role user mapping and role role mapping
  • It supports built-in power users

Such as root or administrator

  • Support for rule matching for multiple built-in operators

For example, hello/world can be mapped to the Hello * pattern

  • Authentication is not supported
  • Managing user or role lists is not supported

Let’s seeCasbinBasic model of

In the Casbin library, it abstracts the access control model into a CONF file based on the PERM metamodel, which has four parts as follows

  • strategy
  • The effect
  • request
  • matcher

Let’s look at one of the simplest models, the CONF model for ACLs

[policy_definition] p = sub, obj, act [role_definition] g = _ _ [policy_effect] e = some(where (p.eft == allow)) [matchers] m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.actCopy the code

Consider a sample policy for the ACL model

p, xiaomt, data1, read
p, xiaomt, data2, write
Copy the code

So let’s write a DEMO

  • main.goFile writeginThe corresponding interface andcasbinThe use of
  • rbac_models.confRBAC CONF file

Let’s write a route, add an interceptor to it, write an interface/API /v1/ Hello, and use the GET method to verify the effect

package main

import (
   "fmt"
   "log"

   "github.com/casbin/casbin"
   xd "github.com/casbin/xorm-adapter"
   "github.com/gin-gonic/gin"
   _ "github.com/go-sql-driver/mysql"
)

// myAuth interceptor
func myAuth(e *casbin.Enforcer) gin.HandlerFunc {
   return func(c *gin.Context) {
      obj := c.Request.URL.RequestURI()
      // Obtain the method
      act := c.Request.Method
      sub := "root"

      // Check whether the policy already exists
      if ok := e.Enforce(sub, obj, act); ok {
         log.Println("Check successfully")
         c.Next()
      } else {
         log.Println("sorry , Check failed")
         c.Abort()
      }
   }
}

func main(a) {
   // Use your own rbac_db
   // Use the default database name casbin. If it does not exist, create it
   a := xd.NewAdapter("mysql"."Root: 123456 @ TCP/mycasbin (127.0.0.1:3306)? charset=utf8".true)

   e := casbin.NewEnforcer("./rbac_models.conf", a)

   // Load the policy from DB
   e.LoadPolicy()

   //new A route
   r := gin.New()

   r.POST("/api/v1/add".func(c *gin.Context) {
      log.Println("add a policy")
      if ok := e.AddPolicy("root"."/api/v1/hello"."GET"); ! ok { log.Println("The strategy already exists")}else {
         log.Println("add successfully ...")}})// Using custom interceptor middleware, every interface access will pass through the interceptor
   r.Use(myAuth(e))
   // Create the request
   r.GET("/api/v1/hello".func(c *gin.Context) {
      fmt.Println("hello wolrd")})// Listen to 127. 0.0.1:8888
   r.Run(": 8888")}Copy the code

For the above xD. NewAdapter read data operation, we can see the concrete implementation

The specific source code is in “github.com/casbin/xorm-adapter” adapter.go

// NewAdapter is the constructor for Adapter.
// dbSpecified is an optional bool parameter. The default value is false.
// It's up to whether you have specified an existing DB in dataSourceName.
// If dbSpecified == true, you need to make sure the DB in dataSourceName exists.
// If dbSpecified == false, the adapter will automatically create a DB named "casbin".
func NewAdapter(driverName string, dataSourceName string, dbSpecified ...bool) *Adapter {
   a := &Adapter{}
   a.driverName = driverName
   a.dataSourceName = dataSourceName

   if len(dbSpecified) == 0 {
      a.dbSpecified = false
   } else if len(dbSpecified) == 1 {
      a.dbSpecified = dbSpecified[0]}else {
      panic(errors.New("invalid parameter: dbSpecified"))}// Open the DB, create it if not existed.
   a.open()

   // Call the destructor when the object is released.
   runtime.SetFinalizer(a, finalizer)

   return a
}
Copy the code

Let’s look at casbin.newenforcer

The source file is enforcer.go in” github.com/casbin/casbin”

NewEnforcer creates an enforcer from a file or DB. Here is the official example. Note the following example

// e := casbin.NewEnforcer("path/to/basic_model.conf", "path/to/basic_policy.csv")
// MySQL DB:
/ / a: = mysqladapter. NewDBAdapter (" mysql ", "mysql_username: mysql_password @ TCP (127.0.0.1:3306)/")
// e := casbin.NewEnforcer("path/to/basic_model.conf", a)
Copy the code
func NewEnforcer(params ...interface{}) *Enforcer {
   e := &Enforcer{}

   parsedParamLen := 0
   // Determine the number of parameters
   if len(params) >= 1 {
      enableLog, ok := params[len(params)- 1]. (bool)
      if ok {
         e.EnableLog(enableLog)

         parsedParamLen++
      }
   }
   // Omit part of the code
   return e
}
Copy the code

The above code, if you are interested, you can paste the code into your own environment

Use a tool like Postman to access the interface and see the effect. You need to configure the mysql database

If you are interested in the gin and interceptors mentioned above, check out the article

  • Share a wave of GIN routing algorithms
  • Take a look at gRPC’s interceptor
  • Gin practice

conclusion

  • What is shared rights management
  • What is Casbin
  • The characteristics of Casbin
  • This is an application case of Casbin

Welcome to like, follow and collect

Dear friends, your support and encouragement are the motivation for me to keep sharing and improve the quality

Ok, so that’s it for this time, how is the backend going to provide the API in the next work? Swaggo is very good

Technology is open, our mentality, should be more open. Embrace change, live in the sun, and strive to move forward.

I am nezha, welcome to like the collection, see you next time ~