001/**
002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com).
003 * <p>
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * <p>
008 *  http://www.apache.org/licenses/LICENSE-2.0
009 * <p>
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package io.jboot.support.shiro.processer;
017
018import org.apache.shiro.SecurityUtils;
019import org.apache.shiro.authz.AuthorizationException;
020import org.apache.shiro.authz.annotation.Logical;
021import org.apache.shiro.authz.annotation.RequiresPermissions;
022import org.apache.shiro.subject.Subject;
023
024
025public class ShiroRequiresPermissionsProcesser implements IShiroAuthorizeProcesser {
026    
027    private final RequiresPermissions requiresPermissions;
028
029    public ShiroRequiresPermissionsProcesser(RequiresPermissions requiresPermissions) {
030        this.requiresPermissions = requiresPermissions;
031    }
032
033    @Override
034    public AuthorizeResult authorize() {
035        try {
036            String[] perms = requiresPermissions.value();
037            Subject subject = SecurityUtils.getSubject();
038
039            if (perms.length == 1) {
040                subject.checkPermission(perms[0]);
041                return AuthorizeResult.ok();
042            }
043            if (Logical.AND.equals(requiresPermissions.logical())) {
044                subject.checkPermissions(perms);
045                return AuthorizeResult.ok();
046            }
047            if (Logical.OR.equals(requiresPermissions.logical())) {
048                // Avoid processing exceptions unnecessarily - "delay" throwing the
049                // exception by calling hasRole first
050                boolean hasAtLeastOnePermission = false;
051                for (String permission : perms)
052                    if (subject.isPermitted(permission))
053                        hasAtLeastOnePermission = true;
054                // Cause the exception if none of the role match, note that the
055                // exception message will be a bit misleading
056                if (!hasAtLeastOnePermission)
057                    subject.checkPermission(perms[0]);
058
059            }
060
061            return AuthorizeResult.ok();
062
063        } catch (AuthorizationException e) {
064            return AuthorizeResult.fail(AuthorizeResult.ERROR_CODE_UNAUTHORIZATION);
065        }
066    }
067}