/* * JBoss, Home of Professional Open Source. * Copyright 2012, Red Hat, Inc., and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package com.gr.project.security.authorization; import static org.picketlink.idm.model.basic.BasicModel.getRole; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import javax.annotation.PostConstruct; import javax.enterprise.context.RequestScoped; import javax.enterprise.inject.Instance; import javax.enterprise.inject.spi.BeanManager; import javax.inject.Inject; import javax.inject.Named; import javax.interceptor.InvocationContext; import javax.servlet.http.HttpServletRequest; import org.apache.deltaspike.security.api.authorization.AccessDeniedException; import org.apache.deltaspike.security.api.authorization.Secures; import org.picketlink.Identity; import org.picketlink.Identity.Stateless; import org.picketlink.idm.IdentityManager; import org.picketlink.idm.RelationshipManager; import org.picketlink.idm.model.Account; import org.picketlink.idm.model.basic.BasicModel; import org.picketlink.idm.model.basic.Role; import com.gr.project.security.authorization.annotation.UserLoggedIn; import com.gr.project.security.model.ApplicationRole; /** * <p> * Provides authorization services for the application. * </p> * * @author Pedro Silva * */ @RequestScoped public class AuthorizationManager { private Map<String, String[]> roleProtectedResources = new HashMap<String, String[]>(); @Inject @Named("resource.wildcard") private String ANY_RESOURCE_PATTERN; @Inject @Stateless private Identity identity; @Inject private Instance<IdentityManager> identityManager; @Inject private Instance<RelationshipManager> relationshipManager; @PostConstruct public void init() { // let's configure which URIs should be protected this.roleProtectedResources.put("/admin/*", new String[] { "Administrator" }); } /** * <p> * Check if a method or type annotated with the {@link com.gr.project.security.authorization.annotation.UserLoggedIn} is being access by an authenticated user. This method * is called before the annotated method is called. * </p> * * @return */ @Secures @UserLoggedIn public boolean isUserLoggedIn() { return identity.isLoggedIn(); } /** * <p> * This authorization method provides the validation logic for resources annotated with the security annotation {@link AllowedRole}. * </p> * <p> * Note that this method is also annotated with {@link Secures}, which is an annotation from Apache DeltaSpike. * This annotation tells the @{link SecurityInterceptor} that this method must be called before the execution of * methods annotated with {@checkDeclaredRoles} in order to perform authorization checks. * </p> * * @param invocationContext * @param manager * @return true if the user can execute the method or class * @throws Exception */ @Secures @AllowedRole public boolean checkDeclaredRoles(InvocationContext invocationContext, BeanManager manager) throws Exception { // administrators can access everything if (hasRole(ApplicationRole.ADMINISTRATOR.name())) { return true; } Object targetBean = invocationContext.getTarget(); AllowedRole declareRoles = targetBean.getClass().getAnnotation(AllowedRole.class); if (declareRoles == null) { declareRoles = invocationContext.getMethod().getAnnotation(AllowedRole.class); } ApplicationRole[] requiredRoles = declareRoles.value(); if (requiredRoles.length == 0) { throw new IllegalArgumentException("@DeclaredRoles does not define any role."); } for (ApplicationRole requiredRole: requiredRoles) { if (hasRole(requiredRole.name())) { return true; } } return false; } public boolean isAdmin() { if (isUserLoggedIn()) { IdentityManager identityManager = getIdentityManager(); RelationshipManager relationshipManager = getRelationshipManager(); return BasicModel.hasRole(relationshipManager, identity.getAccount(), BasicModel.getRole(identityManager, "Administrator")); } return false; } /** * <p> * Check if the current user is allowed to access the requested resource. * </p> * * @param httpRequest * @throws AccessDeniedException If the request is not allowed considering the resource permissions. */ public boolean isAllowed(HttpServletRequest httpRequest) throws AccessDeniedException { final String requestURI = httpRequest.getRequestURI(); Set<Entry<String, String[]>> entrySet = this.roleProtectedResources.entrySet(); for (Entry<String, String[]> entry : entrySet) { if (matches(entry.getKey(), requestURI)) { Identity identity = getIdentity(); if (!identity.isLoggedIn()) { return false; } else { String[] roles = entry.getValue(); for (String roleName : roles) { IdentityManager identityManager = getIdentityManager(); Role role = BasicModel.getRole(identityManager, roleName.trim()); if (role == null) { throw new IllegalStateException("The specified role does not exists [" + role + "]. Check your configuration."); } if (!BasicModel.hasRole(getRelationshipManager(), identity.getAccount(), role)) { return false; } } } } } return true; } private RelationshipManager getRelationshipManager() { return this.relationshipManager.get(); } /** * <p> * Checks if the provided URI matches the specified pattern. * </p> * * @param uri * @param pattern * @return */ private boolean matches(String pattern, String uri) { if (pattern.equals(ANY_RESOURCE_PATTERN)) { return true; } if (pattern.equals(uri)) { return true; } if (pattern.endsWith(ANY_RESOURCE_PATTERN)) { String formattedPattern = pattern.replaceAll("/[*]", "/"); if (uri.contains(formattedPattern)) { return true; } } if (pattern.equals("*")) { return true; } else { return (pattern.startsWith(ANY_RESOURCE_PATTERN) && uri.endsWith(pattern.substring( ANY_RESOURCE_PATTERN.length() + 1, pattern.length()))); } } public boolean hasRole(String roleName) { Account account = getIdentity().getAccount(); Role role = getRole(this.identityManager.get(), roleName); if(role == null) return false; return BasicModel.hasRole(this.relationshipManager.get(), account, role); } private IdentityManager getIdentityManager() { return this.identityManager.get(); } private Identity getIdentity() { return this.identity; } }