Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF 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.samlsample.control; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.apache.directory.fortress.core.AccessMgr; import org.apache.directory.fortress.core.GlobalErrIds; import org.apache.directory.fortress.core.SecurityException; import org.apache.directory.fortress.core.util.Config; import org.apache.directory.fortress.realm.*; import org.apache.log4j.Logger; import org.apache.wicket.Component; import org.apache.directory.fortress.core.model.Permission; import org.apache.directory.fortress.core.model.Session; import org.apache.directory.fortress.core.model.User; import org.springframework.security.providers.ExpiringUsernameAuthenticationToken; import org.springframework.security.saml.SAMLCredential; import javax.servlet.http.HttpServletRequest; import java.util.List; /** * Common static utils and wrappers used by Wicket web apps to make fortress style security calls. * * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> * @version $Rev$ */ public class SecUtils { private static final Logger LOG = Logger.getLogger(SecUtils.class.getName()); private static final String PERMS_CACHED = "perms.cached"; public static final boolean IS_PERM_CACHED = ((Config.getInstance().getProperty(PERMS_CACHED) != null) && (Config.getInstance().getProperty(PERMS_CACHED).equalsIgnoreCase("true"))); public static String FORTRESS_SAML_DEMO_LOGOUT_URL = "/fortress-saml-demo/saml/logout?local=true"; public static String FORTRESS_SAML_UNAUTHORIZED_URL = "/fortress-saml-demo/unauthorized.html"; /** * Return the fortress session that is cached within the wicket session object. * * @param component needed to get handle to wicket session. * @return fortress session object. */ public static Session getSession(Component component) { return ((FtSession) component.getSession()).getSession(); } public static String getUserId(Component component) { String userId = null; Session session = ((FtSession) component.getSession()).getSession(); if (session != null) userId = session.getUserId(); return userId; } private static String getUserId(SAMLCredential credential) { String userId = null; for (org.opensaml.saml2.core.Attribute attr : credential.getAttributes()) { String fname = attr.getFriendlyName(); if (StringUtils.isEmpty(fname)) { break; } else if (fname.equals("uid")) { String vals[] = credential.getAttributeAsStringArray(attr.getName()); userId = vals[0]; break; } } return userId; } private static String getSurName(SAMLCredential credential) { String userId = null; for (org.opensaml.saml2.core.Attribute attr : credential.getAttributes()) { String name = attr.getName(); if (StringUtils.isEmpty(name)) { break; } else if (name.equals("LastName")) { String vals[] = credential.getAttributeAsStringArray(attr.getName()); userId = vals[0]; break; } } return userId; } /** * Enables fortress session on behalf of a java.security.Principal retrieved from the container. * * @param component * @param servletReq * @param j2eePolicyMgr * @param accessMgr * @throws SecurityException */ public static boolean enableFortress(Component component, HttpServletRequest servletReq, J2eePolicyMgr j2eePolicyMgr, AccessMgr accessMgr) throws SecurityException { boolean result = false; // Get the principal from the container: ExpiringUsernameAuthenticationToken principal = (ExpiringUsernameAuthenticationToken) servletReq .getUserPrincipal(); // Is this a secured page && has the User successfully authenticated already? boolean isSecured = principal != null; if (isSecured) { // Only perform this step once per user web session: if (!isLoggedIn(component)) { //String userId = principal.getName(); String userId = getUserId((SAMLCredential) principal.getCredentials()); if (StringUtils.isEmpty(userId)) { // This is default where SSOCircle places email address: //userId = principal.getName(); userId = getSurName((SAMLCredential) principal.getCredentials()); if (StringUtils.isEmpty(userId)) { throw new RuntimeException( "No userid found in SAML assertion for principal" + principal.getName()); } } /* else { SAMLCredential credential = (SAMLCredential)principal.getCredentials(); for ( org.opensaml.saml2.core.Attribute attr : credential.getAttributes()) { String fname = attr.getFriendlyName(); String name = attr.getName(); LOG.info( "saml attribute name; " + name ); String[] attributeValues = credential.getAttributeAsStringArray(name); for( String val : attributeValues ) { LOG.info( "saml attribute value:" + val ); } } } */ // Create the fortress session and assert into the Web app's session along with user's perms: result = SecUtils.initializeFtSession(component, j2eePolicyMgr, accessMgr, userId); } else { result = true; } } else { LOG.warn("Unsecured request: " + servletReq.getRequestURL()); throw new RuntimeException("Unauthenticated user detected for request:" + servletReq.getRequestURL()); } return result; } /** * Returns the fortress arbac perms that are cashed in the wicket session. * * @param component needed to get a handle on the wicket session object. * @return collection of fortress admin perms. */ static List<Permission> getPermissions(Component component) { return ((FtSession) component.getSession()).getPermissions(); } /** * Retrieve RBAC session permissions from Fortress and place in the Wicket session. */ static void getPermissions(Component component, AccessMgr accessMgr) { try { if (IS_PERM_CACHED) { FtSession session = (FtSession) component.getSession(); List<Permission> permissions = accessMgr.sessionPermissions(session.getSession()); ((FtSession) FtSession.get()).setPermissions(permissions); } } catch (org.apache.directory.fortress.core.SecurityException se) { String error = "getPermissions caught SecurityException=" + se; LOG.error(error); throw new RuntimeException(error); } } /** * Is the supplied permission in the wicket session cache? Called by buttons. * if not found, button will be invisible. * * @param permission fortress perm requires {link @Permission#objName} and {link @Permission#opName} are set. * @param component needed to get handle on the wicket session object. * @return true if found, false otherwise */ static boolean isFound(Permission permission, Component component) { List<Permission> permissions = SecUtils.getPermissions(component); return CollectionUtils.isNotEmpty(permissions) && permissions.contains(permission); } /** * Create a Fortress Session and load into a Wicket Session along with perms. * * @param component contains handle to wicket session. * @param j2eePolicyMgr used to call deserize api * @param accessMgr used to call fortress api for role op * @param userId contains the instance of fortress session deserialized. */ static boolean initializeFtSession(Component component, J2eePolicyMgr j2eePolicyMgr, AccessMgr accessMgr, String userId) throws SecurityException { boolean result = false; Session realmSession = null; try { realmSession = j2eePolicyMgr.createSession(new User(userId), true); result = true; } catch (org.apache.directory.fortress.core.SecurityException se) { if (se.getErrorId() == GlobalErrIds.USER_NOT_FOUND) { LOG.info("initializeFtSession User: " + userId + ", not found, terminate login"); } else { String error = "initializeFtSession exception during createSession for user: " + userId + ", error=" + se.getMessage(); LOG.info(error); throw new RuntimeException(error); } } if (result) { synchronized ((FtSession) FtSession.get()) { if (SecUtils.getSession(component) == null) { LOG.info("realmSession user: " + realmSession.getUserId()); // Retrieve user permissions and attach RBAC session to Wicket session: ((FtSession) FtSession.get()).setSession(realmSession); getPermissions(component, accessMgr); } } } return result; } /** * If user has a wicket session then considered logged in. * * @return true if wicket session is not null */ static boolean isLoggedIn(Component component) { boolean isLoggedIn = false; if (getSession(component) != null) { isLoggedIn = true; } return isLoggedIn; } /** * parse a string value: objName.opName * * @param id '.' separated value * @return {@link org.apache.directory.fortress.core.model.Permission} */ static Permission getPermFromId(String id) { Permission perm = null; String[] parts = id.split("\\."); if (parts.length > 1) { String objName = parts[0]; String opName = parts[1]; perm = new Permission(objName, opName); } return perm; } }