/* * Copyright (c) 2011, National Institute of Informatics * * Licensed 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 plugin.idp; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; import edu.internet2.middleware.shibboleth.common.attribute.AttributeRequestException; import edu.internet2.middleware.shibboleth.common.attribute.BaseAttribute; import edu.internet2.middleware.shibboleth.common.attribute.provider.SAML2AttributeAuthority; import edu.internet2.middleware.shibboleth.common.profile.AbstractErrorHandler; import edu.internet2.middleware.shibboleth.common.profile.provider.BaseSAMLProfileRequestContext; import edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfiguration; import edu.internet2.middleware.shibboleth.common.relyingparty.provider.SAMLMDRelyingPartyConfigurationManager; import edu.internet2.middleware.shibboleth.idp.authn.AuthenticationException; import edu.internet2.middleware.shibboleth.idp.authn.LoginContext; import edu.internet2.middleware.shibboleth.idp.util.HttpServletHelper; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import org.opensaml.saml2.metadata.provider.MetadataProvider; import org.opensaml.saml2.metadata.provider.MetadataProviderException; public class SampleFilterPerSP implements Filter { /** web.xmlのパラメータキー */ private static String CONFIGFILES = "Config"; /** ServletContext */ private ServletContext m_servletContext = null; /** SP毎ののattributeフィルタの値 */ private Map allow_config; /** 属性のContext */ private SAML2AttributeAuthority m_saml2AttrAuth; /** RelyingPartyのContext */ private SAMLMDRelyingPartyConfigurationManager m_samlRelyingPartyConfMan; @Override public void destroy() { // TODO 自動生成されたメソッド・スタブ } @Override public void doFilter( ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; // フィルタ条件がない場合は次のフィルタへ if (allow_config.isEmpty()) { filterChain.doFilter(servletRequest, servletResponse); return; } // shibboleth のログイン情報 // see also: https://wiki.shibboleth.net/confluence/display/SHIB2/IdPAuthUserPass LoginContext loginCtx = HttpServletHelper.getLoginContext( HttpServletHelper.getStorageService(m_servletContext), m_servletContext, httpServletRequest); if (loginCtx == null) { // まだログインしていない場合はログイン処理へ filterChain.doFilter(servletRequest, servletResponse); return; } // ログイン結果判定 AuthenticationException authenticationFailure = loginCtx.getAuthenticationFailure(); if (authenticationFailure != null) { filterChain.doFilter(servletRequest, servletResponse); return; } // ログインユーザとSPのエンティティID String spEntityId = loginCtx.getRelyingPartyId(); String userName = loginCtx.getPrincipalName(); // 属性情報リクエスト用の情報 BaseSAMLProfileRequestContext requestCtx = new BaseSAMLProfileRequestContext(); // SPに対応するRelyingParty RelyingPartyConfiguration relyingPartyConfiguration = m_samlRelyingPartyConfMan.getRelyingPartyConfiguration(spEntityId); // メタデータプロバイダ情報 MetadataProvider metadataProvider = m_samlRelyingPartyConfMan.getMetadataProvider(); // IdPのエンティティID String idpEntityId = relyingPartyConfiguration.getProviderId(); // リクエスト情報設定 try { requestCtx.setRelyingPartyConfiguration(relyingPartyConfiguration); requestCtx.setInboundMessageIssuer(spEntityId); requestCtx.setOutboundMessageIssuer(idpEntityId); requestCtx.setPrincipalName(userName); requestCtx.setLocalEntityId(idpEntityId); requestCtx.setPeerEntityId(spEntityId); requestCtx.setLocalEntityMetadata(metadataProvider.getEntityDescriptor(idpEntityId)); requestCtx.setPeerEntityMetadata(metadataProvider.getEntityDescriptor(spEntityId)); requestCtx.setMetadataProvider(metadataProvider); } catch (MetadataProviderException e) { e.printStackTrace(); filterChain.doFilter(servletRequest, servletResponse); return; } // 属性を取得 Map attributes = null; try { attributes = m_saml2AttrAuth.getAttributes(requestCtx); } catch (AttributeRequestException e) { e.printStackTrace(); } if (attributes == null) { filterChain.doFilter(servletRequest, servletResponse); return; } // コンフィグの設定と比較 System.out.println("SampleFilterPerSP spEntityId = " + spEntityId); if (allow_config.containsKey(spEntityId)) { Map filterpersp = allow_config.get(spEntityId); for (BaseAttribute baseattrval : attributes.values()) { if (filterpersp.containsKey(baseattrval.getId())) { Set val = (Set)filterpersp.get(baseattrval.getId()); for (Object obj: baseattrval.getValues()) { if (obj != null && !obj.toString().trim().equals("")) { String attrval = obj.toString(); if (val.contains(attrval)) { // for debug System.out.println("SampleFilterPerSP checked " + baseattrval.getId() + "=" + attrval); filterChain.doFilter(servletRequest, servletResponse); return; } } } } } // for debug System.out.println("SampleFilterPerSP don't match any attributes."); for (BaseAttribute baseattrval : attributes.values()) { for (Object obj: baseattrval.getValues()) { if (obj != null && !obj.toString().trim().equals("")) { String attrval = obj.toString(); System.out.println("SampleFilterPerSP " + baseattrval.getId() + "=" + attrval); } } } doError(servletRequest, servletResponse, spEntityId, userName); return; } filterChain.doFilter(servletRequest, servletResponse); } /** * エラーの場合エラー内容表示 * @param servletResponse * @param spEntityId * @param userName * @throws IOException */ private void doError(ServletRequest servletRequest, ServletResponse servletResponse, String spEntityId, String userName) throws IOException, ServletException { final String PAGE_ERROR = "/error.jsp"; final String errmsg = "Deny you(" + userName + ") login to Service Provider " + spEntityId; // エラーメッセージの表示など Throwable error = new Exception(errmsg); servletRequest.setAttribute(AbstractErrorHandler.ERROR_KEY, error); m_servletContext.getRequestDispatcher(PAGE_ERROR).forward(servletRequest, servletResponse); } @Override public void init(FilterConfig filterConfig) throws ServletException { // web.xmlのコンフィグなど m_servletContext = filterConfig.getServletContext(); allow_config = new HashMap(); String configfilename = filterConfig.getInitParameter(CONFIGFILES); if (configfilename != null) { File conffile = new File(configfilename); if (conffile.exists()) { // ファイルの操作など try { XMLConfiguration xml_config = new XMLConfiguration(conffile); for (int i = 0; i < xml_config.getList("EntityDescriptor[@entityID]").size(); i++) { String spEntityId = xml_config.getString("EntityDescriptor("+i+")[@entityID]"); if (allow_config.containsKey(spEntityId) == true) { System.out.println("SampleFilterPerSP WARNING: ignore duplicated " + spEntityId + " because it is already configured"); continue; } Map submap = new HashMap(); String[] attributeID = xml_config.getStringArray("EntityDescriptor("+i+").Attribute[@attributeID]"); String[] attribute = xml_config.getStringArray("EntityDescriptor("+i+").Attribute"); for (int j = 0; j < attributeID.length; j++) { if (submap.containsKey(attributeID[j]) == false) { submap.put(attributeID[j], new HashSet()); } submap.get(attributeID[j]).add(attribute[j]); } allow_config.put(spEntityId, submap); } } catch (ConfigurationException e) { throw new ServletException(e); } } System.out.println("SampleFilterPerSP config-key-value:"); for(Map.Entry e : allow_config.entrySet()) { System.out.println("SampleFilterPerSP " + e.getKey() + " : " + e.getValue()); } } // 取得した属性情報 m_saml2AttrAuth = (SAML2AttributeAuthority) filterConfig.getServletContext().getAttribute("shibboleth.SAML2AttributeAuthority"); // relying-partyの情報 m_samlRelyingPartyConfMan = (SAMLMDRelyingPartyConfigurationManager) filterConfig.getServletContext().getAttribute( "shibboleth.RelyingPartyConfigurationManager"); } }