/**
* Licensed to the Austrian Association for Software Tool Integration (AASTI)
* under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. The AASTI licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openengsb.core.services.internal.security;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.ArrayUtils;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ThreadContext;
import org.openengsb.core.api.security.service.AccessDeniedException;
import org.openengsb.domain.authorization.AuthorizationDomain;
import org.openengsb.domain.authorization.AuthorizationDomain.Access;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This interceptor is used to enforce access control on services. Secure services are supposed to be advised with this
* interceptor.
*
* Either the {@link org.openengsb.core.api.ConnectorRegistrationManager} or the developer himself must take care of
* this. To configure an advice in blueprint you may use {@link org.openengsb.core.common.ProxyFactoryBean}.
*/
public class SecurityInterceptor implements MethodInterceptor {
private AuthorizationDomain authorizer;
private static final Logger LOGGER = LoggerFactory.getLogger(SecurityInterceptor.class);
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
LOGGER.debug("intercepting method {}", mi.getMethod());
// don't control access to Object-methods like toString or hashcode
if (ArrayUtils.contains(Object.class.getMethods(), mi.getMethod())) {
LOGGER.info("is Object-method; skipping");
return mi.proceed();
}
Subject subject = ThreadContext.getSubject();
if (subject == null || !subject.isAuthenticated()) {
throw new AccessDeniedException("no authentication was found in context");
}
if (RootAuthenticationToken.USERNAME.equals(subject.getPrincipal())) {
// this action is executed in a root-context
return mi.proceed();
}
String username = (String) subject.getPrincipal();
Access decisionResult = authorizer.checkAccess(username, mi);
if (decisionResult != Access.GRANTED) {
LOGGER.warn("Access denied because result was {}", decisionResult);
throw new AccessDeniedException();
}
LOGGER.debug("Access was granted");
return mi.proceed();
}
public void setAuthorizer(AuthorizationDomain authorizer) {
this.authorizer = authorizer;
}
}