/**
* Copyright (c) 2013-2016, The SeedStack authors <http://seedstack.org>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.seedstack.seed.security.internal;
import org.apache.commons.lang.ArrayUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.seedstack.seed.security.AuthorizationException;
import org.seedstack.seed.security.Role;
import org.seedstack.seed.security.Scope;
import org.seedstack.seed.security.SecuritySupport;
import org.seedstack.seed.security.SimpleScope;
import org.seedstack.seed.security.internal.authorization.ScopePermission;
import org.seedstack.seed.security.internal.authorization.SeedAuthorizationInfo;
import org.seedstack.seed.security.principals.PrincipalProvider;
import org.seedstack.seed.security.principals.Principals;
import org.seedstack.seed.security.principals.SimplePrincipalProvider;
import javax.inject.Inject;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
class ShiroSecuritySupport implements SecuritySupport {
@Inject
private Set<Realm> realms;
@Override
public PrincipalProvider<?> getIdentityPrincipal() {
Subject subject = SecurityUtils.getSubject();
if (subject.getPrincipal() instanceof PrincipalProvider) {
return (PrincipalProvider<?>) subject.getPrincipal();
}
return Principals.identityPrincipal("");
}
@Override
public Collection<PrincipalProvider<?>> getOtherPrincipals() {
Collection<PrincipalProvider<?>> principals = new ArrayList<>();
PrincipalCollection principalCollection = SecurityUtils.getSubject().getPrincipals();
if (principalCollection == null) {
return Collections.emptyList();
}
for (Object shiroPrincipal : principalCollection.asList()) {
if (shiroPrincipal instanceof PrincipalProvider) {
principals.add((PrincipalProvider<?>) shiroPrincipal);
}
}
return principals;
}
@Override
public <T extends Serializable> Collection<PrincipalProvider<T>> getPrincipalsByType(Class<T> principalClass) {
return Principals.getPrincipalsByType(getOtherPrincipals(), principalClass);
}
@Override
public Collection<SimplePrincipalProvider> getSimplePrincipals() {
return Principals.getSimplePrincipals(getOtherPrincipals());
}
@Override
public SimplePrincipalProvider getSimplePrincipalByName(String principalName) {
return Principals.getSimplePrincipalByName(getOtherPrincipals(), principalName);
}
@Override
public boolean isAuthenticated() {
return SecurityUtils.getSubject().isAuthenticated();
}
@Override
public boolean isPermitted(String permission) {
return SecurityUtils.getSubject().isPermitted(permission);
}
@Override
public boolean isPermitted(String permission, Scope... scopes) {
if (ArrayUtils.isEmpty(scopes)) {
return isPermitted(permission);
}
boolean isPermitted = true;
for (Scope scope : scopes) {
isPermitted = isPermitted && SecurityUtils.getSubject().isPermitted(new ScopePermission(permission, scope));
}
return isPermitted;
}
@Override
public boolean isPermittedAll(String... permissions) {
return SecurityUtils.getSubject().isPermittedAll(permissions);
}
@Override
public boolean isPermittedAny(String... permissions) {
boolean[] bools = SecurityUtils.getSubject().isPermitted(permissions);
return ArrayUtils.contains(bools, true);
}
@Override
public void checkPermission(String permission) {
try {
SecurityUtils.getSubject().checkPermission(permission);
} catch (org.apache.shiro.authz.AuthorizationException e) {
throw new AuthorizationException("Subject doesn't have permission " + permission, e);
}
}
@Override
public void checkPermission(String permission, Scope... scopes) {
try {
if (ArrayUtils.isEmpty(scopes)) {
checkPermission(permission);
} else {
for (Scope scope : scopes) {
SecurityUtils.getSubject().checkPermission(new ScopePermission(permission, scope));
}
}
} catch (org.apache.shiro.authz.AuthorizationException e) {
throw new AuthorizationException("Subject doesn't have permission " + permission, e);
}
}
@Override
public void checkPermissions(String... stringPermissions) {
Collection<org.apache.shiro.authz.Permission> permissions = new ArrayList<>();
for (String stringPermission : stringPermissions) {
permissions.add(new ScopePermission(stringPermission));
}
try {
SecurityUtils.getSubject().checkPermissions(permissions);
} catch (org.apache.shiro.authz.AuthorizationException e) {
throw new AuthorizationException("Subject doesn't have permissions " + Arrays.toString(stringPermissions), e);
}
}
@Override
public boolean hasRole(String roleIdentifier) {
return SecurityUtils.getSubject().hasRole(roleIdentifier);
}
@Override
public boolean hasRole(String roleIdentifier, Scope... scopes) {
if (ArrayUtils.isEmpty(scopes)) {
return hasRole(roleIdentifier);
}
Role role = null;
Set<Role> roles = getRoles();
for (Role role2 : roles) {
if (role2.getName().equals(roleIdentifier)) {
role = role2;
break;
}
}
if (role == null) {
return false;
}
return role.getScopes().containsAll(Arrays.asList(scopes));
}
@Override
public boolean hasAllRoles(String... roleIdentifiers) {
return SecurityUtils.getSubject().hasAllRoles(Arrays.asList(roleIdentifiers));
}
@Override
public boolean hasAnyRole(String... roleIdentifiers) {
boolean[] hasRoles = SecurityUtils.getSubject().hasRoles(Arrays.asList(roleIdentifiers));
return ArrayUtils.contains(hasRoles, true);
}
@Override
public void checkRole(String roleIdentifier) {
try {
SecurityUtils.getSubject().checkRole(roleIdentifier);
} catch (org.apache.shiro.authz.AuthorizationException e) {
throw new AuthorizationException("Subject doesn't have role " + roleIdentifier, e);
}
}
@Override
public void checkRoles(String... roleIdentifiers) {
try {
SecurityUtils.getSubject().checkRoles(roleIdentifiers);
} catch (org.apache.shiro.authz.AuthorizationException e) {
throw new AuthorizationException("Subject doesn't have roles " + Arrays.toString(roleIdentifiers), e);
}
}
@Override
public void logout() {
SecurityUtils.getSubject().logout();
}
private SeedAuthorizationInfo getAuthorizationInfo(Realm realm) {
SeedAuthorizationInfo authzInfo = null;
if (realm instanceof ShiroRealmAdapter) {
AuthorizationInfo tmpInfo = ((ShiroRealmAdapter) realm).getAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
authzInfo = (SeedAuthorizationInfo) tmpInfo;
}
return authzInfo;
}
@Override
public Set<Role> getRoles() {
Set<Role> roles = new HashSet<>();
for (Realm realm : realms) {
SeedAuthorizationInfo authzInfo = getAuthorizationInfo(realm);
if (authzInfo != null) {
for (Role role : authzInfo.getSeedRoles()) {
roles.add(Role.unmodifiableRole(role));
}
}
}
return roles;
}
@Override
public Set<SimpleScope> getSimpleScopes() {
Set<SimpleScope> simpleScopes = new HashSet<>();
for (Role role : getRoles()) {
simpleScopes.addAll(role.getScopesByType(SimpleScope.class));
}
return simpleScopes;
}
@Override
public String getHost() {
Session s = SecurityUtils.getSubject().getSession(false);
if (s == null) {
return null;
}
return s.getHost();
}
}