Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”.
Welcome to the Nuggets, this is little Chetto _ ridiculous 😁😁.
Let’s pick up where we left off, and if you want to see what’s going on, you can go back to the last post, “User rights can Still Play this way, Overturn Your Perception (1).”
Remember the three topics we talked about in our last post?
- JavaScript base bit operations
- Judgment of authority
- After use feeling
One – base bit operation
1.2. An operation
The bit operators in JavaScript have
The operator | usage | describe |
---|---|---|
Bitwise AND (AND) | a & b | For each bit, the result is 1 only if the corresponding bit bits of both operands are 1; otherwise, it is 0. |
Bitwise OR (OR) | a | b | For each bit, the result is 1 if there is at least one 1 in the corresponding bit of the two operands, and 0 otherwise. |
Bitwise XOR | a ^ b | For each bit, the result is 1 if there is one and only one 1 in the corresponding bit of the two operands, and 0 otherwise. |
Bitwise NOT | ~a | Invert the operand’s bits, i.e., 0 becomes 1,1 becomes 0. |
Left shift | a << b | Shift the binary form of A to the left by b (< 32) bits, filling the right with zeros. |
There’s a sign shift to the right | a >> b | Move the binary representation of A to the right by b (< 32) bits, discarding the removed bits. |
Unsigned shift to the right | a >>> b | Move the binary representation of A to the right by b (< 32) bits, discard the removed bits, and fill in the left side with zeros. |
In the last post we covered only bitwise or (^), and we’ll cover the rest
1.2.5 Signed Left shift (<<)
A signed left shift moves all bits of a 32-bit binary number to the left by a specified number of digits. Such as:
var num = 2; // Binary 10
num = num << 5; // Binary 1000000, decimal 64
Copy the code
If we want 2 to the n, we can do this:
function power(n) {
return 1 << n;
}
power(5); / / 32
Copy the code
1 in binary is 01, 5 bits to the left is 0100000, and 2 to the fifth is 32 in decimal.
1.2.6 Move the Signed Right (>>)
A signed right shift moves all bits of a 32-bit binary number to the right by a specified number of digits. Such as:
var num = 64; // Binary 1000000
num = num >> 5; // Binary 10, decimal 2
Copy the code
To find one half of a number:
var num = 64 >> 1; / / 32
Copy the code
Signed left and right shifts do not affect sign bits.
1.2.7 Unsigned Right Shift (>>>)
The unsigned right shift of a positive number is the same as the signed right shift. An unsigned right shift of a negative number moves the sign bit with it, and an unsigned right shift treats the binary of a negative number as the binary of a positive number:
var num = -64; / / 11111111111111111111111111000000
num = num >>> 5; / / 134217726
Copy the code
So, we can use the unsigned right shift to determine whether a number is positive or negative:
function isPos(n) {
return (n === (n >>> 0))?true : false;
}
isPos(-1); // false
isPos(1); // true
Copy the code
-1>>>0 has not been moved to the right, but the -1 binary has become a positive binary:
11111111111111111111111111111111
Copy the code
So the value of -1>>>0 is 4294967295.
Above is our JavaScript base bit operation, interested partners can continue to further imagine these knowledge, we base bit operation here first, next we will talk about our second topic
2. Judgment of authority
In our traditional permission system, the permission judgment is maintained by association relation. In the background, the data should be stored in a lot of tables, storing a lot of related fields, such as the association between users and permissions, and the association between users and roles. The larger the system, the more relationships it has, and the harder it is to maintain. Introducing bit operation can solve this problem ingeniously.
Before we get to “the use of bitwise operations in privilege systems,” let’s assume two premises on which all of the following discussion is based:
Each permission code is unique (this is obvious)
The binary form of all permission codes, with one and only one bit of value 1 and all others 0 (2^n)
If the user permission and permission code are all represented by two-level numbers, and combined with the example of bit operation above, the characteristics of bit operation are analyzed, we can find:
| can be used to give permission
& can be used to verify permissions
File permissions in Linux are divided into read, write, and execute, with letters and numbers and other forms:
permissions | The letter said | The figures show that the | binary |
---|---|---|---|
read | r | 4 | 0b100 |
write | w | 2 | 0b010 |
perform | x | 1 | 0b001 |
As you can see, permissions are represented by 1, 2, and 4 (that is, 2^n). When converted to binary, only one digit is 1 and the rest is 0. Let’s take a look at a few examples of how you can take advantage of binary features to add, verify, and remove permissions.
2.1 Adding Rights
First, confirm the permission list with the background, that is, each kind of permission corresponds to a unique permission code
We are using hexadecimal definition, whether hexadecimal or binary, including menus, buttons, data, as follows:
Permission In English | The hexadecimal code of the permission | Chinese name of permission |
---|---|---|
HighRisk | 0x00001 | Advanced risk control management |
MiddleRisk | 0x00002 | Intermediate risk control management |
LowRisk | 0x00004 | Low level risk control management |
To define a permission list is to add a permission
let permission = {
HighRisk: 0x00001.MiddleRisk: 0x00002.LowRisk: 0x00004
}
/ / all assign permissions to users (using the | operation)
let user = permission.HighRisk | permission.HighRisk | permission.LowRisk
console.log(user)
/ / 5
console.log(user.toString(2))
/ / 101
Copy the code
| after operation, can be used to direct the budget after the results to the background, or on a binary to the background, this is all your own with the terms of the background
2.2 Verifying Permissions
After adding permissions, we verify permissions:
let permission = {
HighRisk: 0x00001.MiddleRisk: 0x00002.LowRisk: 0x00004
}
// Assign HighRisk MiddleRisk permissions to the user
let user = permission.HighRisk | permission.MiddleRisk
// user = 3
// user = 0x00003 (hexadecimal)
console.log((user & permission.HighRisk) === permission.HighRisk) // true has the HighRisk permission
console.log((user & permission.MiddleRisk) === permission.MiddleRisk) // True has MiddleRisk permission
console.log((user & permission.LowRisk) === permission.LowRisk) // false does not have LowRisk permission
Copy the code
As expected, the user permissions & permissions code === permissions code can determine whether the user has the permissions.
2.3 Deleting Permission
We spoke with | give permission, use & judgment authority, then remove permissions? The essence of a delete permission is to reset a 1 at a specified location to 0. In the previous example, the user has the permission 0x00003, HighRisk and MiddleRisk. Now, if you want to remove the permission from MiddleRisk, you essentially change the permission to 0x00002.
So how do you do it? In fact, there are two solutions, the simplest one is xor ^. According to the introduction above, “if there is only one and only one 1 in the corresponding bit of the two operands, the result is 1; otherwise, it is 0”, so xor is actually toggle, if there is no, it increases; if there is, it decreases:
let permission = {
HighRisk: 0x00001.MiddleRisk: 0x00002.LowRisk: 0x00004
}
let user = 0x00003 1. // Have HighRisk MiddleRisk permissions
// Perform an xor operation to remove the MiddleRisk permission
user = user ^ permission.MiddleRisk
console.log((user & permission.HighRisk) === permission.HighRisk) // true has the HighRisk permission
console.log((user & permission.MiddleRisk) === permission.MiddleRisk) // False has no MiddleRisk permission
console.log((user & permission.LowRisk) === permission.LowRisk) // false does not have LowRisk permission
console.log(user.toString(16)) // Now user is 0x00002
// Perform another xOR operation
user = user ^ permission.MiddleRisk
console.log((user & permission.HighRisk) === permission.HighRisk) // true has the HighRisk permission
console.log((user & permission.MiddleRisk) === permission.MiddleRisk) // True has MiddleRisk permission
console.log((user & permission.LowRisk) === permission.LowRisk) // false does not have LowRisk permission
console.log(user.toString(16)) // Now user is changed back to 0x00003
Copy the code
So what if you simply want to delete permissions (instead of adding and subtracting permissions)? The answer is to execute &(~code), and then execute and:
let permission = { HighRisk: 0x00001, MiddleRisk: 0x00002, LowRisk: 0x00004} let user = 0x00003 1. Delete the MiddleRisk permission user = user & (~ permission.middlerisk) console.log((user & permission.highrisk) === // true has HighRisk permission console.log((user & permission.middlerisk) === permission.middlerisk) // False has no MiddleRisk permission console.log((user & permission.lowrisk) === permission.lowrisk) // false has no MiddleRisk permission Console. log(user.tostring (16)) // Now user is 0x00002 // Perform another xor operation user = user & (~ permission.MiddleRisk) Console. log((user & permission.highrisk) === permission.highrisk) // true Has HighRisk permission console.log((user &) MiddleRisk) // true has MiddleRisk permission console.log((user & permission.lowrisk) === // false No LowRisk permission console.log(user.tostring (16)) // Now user is 0x00002Copy the code
The above is I use the base bit operation to do the actual logic of authority judgment, we can try!!
3. Afterfeeling
If you design a permissions system according to the most widely used RBAC model, you will typically have several entities: applications, permissions, roles, and users. User permissions can come directly from permissions or roles:
An application has multiple permissions
Permissions and roles are many-to-many
Users and roles have a many-to-many relationship
The relationship between users and permissions is many-to-many
In this model, there are generally tables of the corresponding relationship between users and permissions, users and roles, and roles and permissions. Imagine a mall background permission management system, there may be tens of thousands, or even hundreds of thousands of stores (applications), each store may have dozens of users, roles, permissions. As the business continues to grow, the three mapping tables just mentioned get bigger and harder to maintain.
The method of base conversion can omit the corresponding relation table, reduce query and save space. Of course, it is not without harm to omit the correspondence, such as the following questions:
How to find my permissions efficiently?
How to efficiently find all users with a certain permission?
How to control the validity period of permissions?
Therefore, the base conversion scheme is suitable for the scenario where the number of users, permissions, and roles in each application is relatively small.
I suggest you try this method, after all, can improve the efficiency, why not?
Creation is not easy, please support more, little like, little attention and collection, is my biggest support, thank you for watching my article, here is a small cut picture son _ ridiculous