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.RequiresRoles;
022
023import java.util.Arrays;
024
025
026public class ShiroRequiresRolesProcesser implements IShiroAuthorizeProcesser {
027
028    private final RequiresRoles requiresRoles;
029
030    public ShiroRequiresRolesProcesser(RequiresRoles requiresRoles) {
031        this.requiresRoles = requiresRoles;
032    }
033
034
035    @Override
036    public AuthorizeResult authorize() {
037        String[] roles = requiresRoles.value();
038        try {
039            if (roles.length == 1) {
040                SecurityUtils.getSubject().checkRole(roles[0]);
041                return AuthorizeResult.ok();
042            }
043            if (Logical.AND.equals(requiresRoles.logical())) {
044                SecurityUtils.getSubject().checkRoles(Arrays.asList(roles));
045                return AuthorizeResult.ok();
046            }
047            if (Logical.OR.equals(requiresRoles.logical())) {
048                // Avoid processing exceptions unnecessarily - "delay" throwing the exception by calling hasRole first
049                boolean hasAtLeastOneRole = false;
050                for (String role : roles) if (SecurityUtils.getSubject().hasRole(role)) hasAtLeastOneRole = true;
051                // Cause the exception if none of the role match, note that the exception message will be a bit misleading
052                if (!hasAtLeastOneRole) SecurityUtils.getSubject().checkRole(roles[0]);
053            }
054            
055            return AuthorizeResult.ok();
056
057        } catch (AuthorizationException e) {
058            return AuthorizeResult.fail(AuthorizeResult.ERROR_CODE_UNAUTHORIZATION);
059        }
060
061    }
062}