Apache Shiro learning record 4 and apacheshiro record 4

Source: Internet
Author: User
Tags addall

Apache Shiro learning record 4 and apacheshiro record 4

I read the third chapter of the tutorial today... it's about authorization ...... as before ..... I also studied it myself .... I think how to read the tutorial ..... in general, there are a few excellent tutorials .... however, in some cases, it is too little .... and these places are quite difficult .. for example, section 3.5 Authorizer, PermissionResolver, and RolePermissionResolver... maybe the author thinks it takes too much space to talk about too many classes ..... but it seems quite uncomfortable to me. 0 .... now that I have mentioned this, I want to understand ..... otherwise it will be too tangled .... so we have this learning record... record my understanding of Shiro authorization

 

Subject

I started my research here from subject. isPermittedAll ("system: view...

As I wrote in my previous Learning Record, Subject is just an interface, and its implementation class is the DelegatingSubject class.

1     public boolean isPermittedAll(String... permissions) {2         return hasPrincipals() && securityManager.isPermittedAll(getPrincipals(), permissions);3     }

 

Authorization and authentication are too similar. Here, the subject actually delegates securityManager for specific processing (2nd rows ).

 

SecurityManager

The securityManager implementation class is defasecursecuritymanager... the N-layer parent class of DefaultSecurityManager contains the isPermitted method.

1     public boolean isPermittedAll(PrincipalCollection principals, String... permissions) {2         return this.authorizer.isPermittedAll(principals, permissions);3     }

We can see that .... shiro's authentication and authorization are really similar... here, authorization is to authorize the authorizer to perform specific authorization, just as I mentioned in my article on authentication, authentication is to entrust authenticator to do the same.

 

ModularRealmAuthorizer

I want to try again... ModularRealmAuthorizer and ModularRealmAuthenticator are really brothers... I almost got the wrong name ....

 1     public boolean isPermittedAll(PrincipalCollection principals, String... permissions) { 2         assertRealmsConfigured(); 3         if (permissions != null && permissions.length > 0) { 4             for (String perm : permissions) { 5                 if (!isPermitted(principals, perm)) { 6                     return false; 7                 } 8             } 9         }10         return true;11     }

Here we extract permissions one by one and call isPermitted (principals, perm) method To see if the user has the permission to perm (5th rows )...........

If all values are included, true is returned. Otherwise, false is returned.

Let's take a look at the isPermitted method.

 1     public boolean isPermitted(PrincipalCollection principals, String permission) { 2         assertRealmsConfigured(); 3         for (Realm realm : getRealms()) { 4             if (!(realm instanceof Authorizer)) continue; 5             if (((Authorizer) realm).isPermitted(principals, permission)) { 6                 return true; 7             } 8         } 9         return false;10     }

From this (row 5th), we can see that ModularRealmAuthorizer actually calls Realm's isPermitted ....

 

AuthorizingRealm
 1     public boolean isPermitted(PrincipalCollection principals, String permission) { 2         Permission p = getPermissionResolver().resolvePermission(permission); 3         return isPermitted(principals, p); 4     } 5  6     public boolean isPermitted(PrincipalCollection principals, Permission permission) { 7         AuthorizationInfo info = getAuthorizationInfo(principals); 8         return isPermitted(permission, info); 9     }10 11     private boolean isPermitted(Permission permission, AuthorizationInfo info) {12         Collection<Permission> perms = getPermissions(info);13         if (perms != null && !perms.isEmpty()) {14             for (Permission perm : perms) {15                 if (perm.implies(permission)) {16                     return true;17                 }18             }19         }20         return false;21     }

So how does Realm handle it?

Call PermissionResolver In the first method to convert the permission of the string to be verified into a real Permission object... this is an important step (but PermissionResolver is also useful in the third method, so we won't mention it here )....

Then, in the second method, call the getAuthorizationInfo (principals) of Realm based on the imported principals to get the AuthorizationInfo .... you must be familiar with this... because if you write Realm, the getAuthorizationInfo method will be overwritten .. the user permission can be obtained in the returned AuthenorizationInfo... it's just a string ......

Then the third method .... line 3: Convert info into a set of Permission objects... then, traverse the set and compare it with the passed permission to see if the user's permission includes (implies) The passed permission ....

 

 1     private Collection<Permission> getPermissions(AuthorizationInfo info) { 2         Set<Permission> permissions = new HashSet<Permission>(); 3  4         if (info != null) { 5             Collection<Permission> perms = info.getObjectPermissions(); 6             if (!CollectionUtils.isEmpty(perms)) { 7                 permissions.addAll(perms); 8             } 9             perms = resolvePermissions(info.getStringPermissions());10             if (!CollectionUtils.isEmpty(perms)) {11                 permissions.addAll(perms);12             }13 14             perms = resolveRolePermissions(info.getRoles());15             if (!CollectionUtils.isEmpty(perms)) {16                 permissions.addAll(perms);17             }18         }19 20         if (permissions.isEmpty()) {21             return Collections.emptySet();22         } else {23             return Collections.unmodifiableSet(permissions);24         }25     }

How do I extract a Permission object from an AuthorizationInfo object that contains permissions in the form of a user string?

From the above method, we can see that the permission comes from three methods and the merged ..info. getObjectPermissions ()..... resolvePermissions (info. getStringPermissions () and resolveRolePermissions (info. getRoles ())....

The first method info. getObjectPermissions () does not know what it is doing .... I still don't understand the comments of the source document (% >_< % )...... I only wrote one demo in Shiro ....... I really don't know ......

The second method, resolvePermissions (info. getStringPermissions (), is very important. You need to mention WildcardPermissionResolver and WildcardPermission... and so on ....

The third method resolveRolePermissions (info. getRoles () I think it is a reserved method .... the RolePermissionResolver interface subclass is used for specific processing .... but Shiro does not provide any implementation... you can take a look at the tutorial... kaitao's tutorial shows his implementation ..... I have read the comments of the source document .... I want to explain it in terms of slag skill that I cannot reach 500 in English (=. =) in general, it means that in some cases, only the subject role can be obtained, but there is no permission. In this case, the RolePermissionResolver can be used to interpret the permission according to the role... well .... that's basically what it means... do not hit me wrong .... Σ (° △° |) percentile )︴

 

Then the focus is naturally the second method resolvePermissions (info. getStringPermissions ....

 1     private Collection<Permission> resolvePermissions(Collection<String> stringPerms) { 2         Collection<Permission> perms = Collections.emptySet(); 3         PermissionResolver resolver = getPermissionResolver(); 4         if (resolver != null && !CollectionUtils.isEmpty(stringPerms)) { 5             perms = new LinkedHashSet<Permission>(stringPerms.size()); 6             for (String strPermission : stringPerms) { 7                 Permission permission = getPermissionResolver().resolvePermission(strPermission); 8                 perms.add(permission); 9             }10         }11         return perms;12     }

So how does Shiro convert the String permission into a real Permission object?

The resolvePermission method of PermissionResolver will be used (as can be seen from the above 7th rows )...

 

 

WildcardPermissionResolver

WildcardPermissionResolver is the default Implementation of PermissionResolver in Shiro ....

Check whether the class name is really tall... but the code is actually super short ....

 1 public class WildcardPermissionResolver implements PermissionResolver { 2  3     /** 4      * Returns a new {@link WildcardPermission WildcardPermission} instance constructed based on the specified 5      * <tt>permissionString</tt>. 6      * 7      * @param permissionString the permission string to convert to a {@link Permission Permission} instance. 8      * @return a new {@link WildcardPermission WildcardPermission} instance constructed based on the specified 9      *         <tt>permissionString</tt>10      */11     public Permission resolvePermission(String permissionString) {12         return new WildcardPermission(permissionString);13     }14 }

That is, a new WildcardPermission is returned ....

 

WildcardPermission
1     public WildcardPermission(String wildcardString) {2         this(wildcardString, DEFAULT_CASE_SENSITIVE);3     }4 5     public WildcardPermission(String wildcardString, boolean caseSensitive) {6         setParts(wildcardString, caseSensitive);7     }

The main constructor method is to call the setParts method... a bit more... DEFAULT_CASE_SENSITIVE is false by default... that is, the string permission is case-insensitive ~ (System: view and System: vIew are a few minutes)

 

 1     protected void setParts(String wildcardString, boolean caseSensitive) { 2         if (wildcardString == null || wildcardString.trim().length() == 0) { 3             throw new IllegalArgumentException("Wildcard string cannot be null or empty. Make sure permission strings are properly formatted."); 4         } 5  6         wildcardString = wildcardString.trim(); 7  8         List<String> parts = CollectionUtils.asList(wildcardString.split(PART_DIVIDER_TOKEN)); 9 10         this.parts = new ArrayList<Set<String>>();11         for (String part : parts) {12             Set<String> subparts = CollectionUtils.asSet(part.split(SUBPART_DIVIDER_TOKEN));13             if (!caseSensitive) {14                 subparts = lowercase(subparts);15             }16             if (subparts.isEmpty()) {17                 throw new IllegalArgumentException("Wildcard string cannot contain parts with only dividers. Make sure permission strings are properly formatted.");18             }19             this.parts.add(subparts);20         }21 22         if (this.parts.isEmpty()) {23             throw new IllegalArgumentException("Wildcard string cannot contain only dividers. Make sure permission strings are properly formatted.");24         }25     }

So what does the setParts method do?

This method is mainly used to assign values to the WildcardPermission member List <Set <String> parts... let's take a look at the separator ....

Protected static final String WILDCARD_TOKEN = "*";
Protected static final String PART_DIVIDER_TOKEN = ":";
Protected static final String SUBPART_DIVIDER_TOKEN = ",";

Then let's take a look at the code, so there is no problem... I don't think there is anything to say about this code... let me give you a few examples... maybe it's more straightforward ....

If the user's string permission is "system: user: create, view"

The size of the List of parts member domains is 3. The first set contains system... the second set contains user... the size of the third set is 2, including create and view

The constructor and setParts do these things! Not much ....

 

Okay... the passed string Permission to be checked is now converted into a Permission object .... the user's string permissions are also converted into Permission objects .... so how can we determine whether a user has the permission to pass in?

In the previous AuthorizingRealm section, I found that perm. implies (permission) is called to determine whether or not it contains ....

Please note that... perm is the user's permission... permission is the permission to pass in for detection...

Let's take a look at the implies method ....

 

 1     public boolean implies(Permission p) { 2         // By default only supports comparisons with other WildcardPermissions 3         if (!(p instanceof WildcardPermission)) { 4             return false; 5         } 6  7         WildcardPermission wp = (WildcardPermission) p; 8  9         List<Set<String>> otherParts = wp.getParts();10 11         int i = 0;12         for (Set<String> otherPart : otherParts) {13             // If this permission has less parts than the other permission, everything after the number of parts contained14             // in this permission is automatically implied, so return true15             if (getParts().size() - 1 < i) {16                 return true;17             } else {18                 Set<String> part = getParts().get(i);19                 if (!part.contains(WILDCARD_TOKEN) && !part.containsAll(otherPart)) {20                     return false;21                 }22                 i++;23             }24         }25 26         // If this permission has more parts than the other parts, only imply it if all of the other parts are wildcards27         for (; i < getParts().size(); i++) {28             Set<String> part = getParts().get(i);29             if (!part.contains(WILDCARD_TOKEN)) {30                 return false;31             }32         }33 34         return true;35     }

The code is like this... but it may take a lot of space to explain .... so I still think the example is faster ...... in fact, this method is to compare two Permission parts ....

Comparison is performed in part... comparison between List [0] and List [0] (first loop of the first )... then compare List [1] With List [1] (the second loop of the first )....

For example, if the user permission is "*: user, admin: view", the permission to be checked is "system: guest: view"

The first round of comparison of the first for... see the code line 19th... because the [0] of the user parts is *! Part. contains (WILDCARD_TOKEN) is false .. So continue to the next round of for loop... it means that * must contain system

Then go to the second round of! Part. contains (WILDCARD_TOKEN) is true .. So check it! Part. containsAll (otherPart )...

The variable part is a collection of user and admin strings... otherPart is a collection of string guest ..! Part. containsAll (otherPart) returns true .. so if is true... so return false .. that is, the user does not have the permission to pass in the detection (of course, this conclusion is not obtained so quickly .. in ModularRealmAuthorizer, if there are multiple realm instances, all realm instances must return false to determine that the user does not have this permission .. because the program may configure multiple Realm... multiple Realm may grant different permissions to a user... therefore, each Realm must be checked to know whether the user package does not contain the permission to be checked... this is simple .. everyone knows this .. I just want to remind you a little .. I just assume that I have configured a realm ..... haha )...

 

I have read the implies method process... I want to know why user: * Matches user: view: 123, and *: view does not match system: user: view ....

When the length of user permission m is less than the length of incoming permission n, the first for of the implies method can be up to m times to know whether the returned value is false or true .. the next n-m comparison won't be done...

When the length of user permission m is greater than the length of permission n, first compare the first for n times in the implies method. If there is still no result... make another 2nd .. check the part from patrs [n-m] to parts M-1 .. if any of these parts is not *, it means that the user does not have the permission to pass in for detection...

 

The above is my understanding of Shiro authorization today ....

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.