我使用WSO2和SSOCircle以及Spring-SAML扩展。我们目前正在测试配置,并在我们的应用程序上下文中定义了2个IdP和2个SP。因此,目前,我们在spring xml配置中有2个静态定义的IdP,并且正在工作。出于测试目的,我们结合使用CachingMetadataManager和ResourceBackedMetadataProvider,因此IdP元数据构建在我们的WAR档案中。样本:
<bean id="metadata" class="org.springframework.security.saml.metadata.CachingMetadataManager">
<constructor-arg>
<list>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
<constructor-arg>
<bean class="org.opensaml.saml2.metadata.provider.ResourceBackedMetadataProvider">
<constructor-arg>
<bean class="java.util.Timer"/>
</constructor-arg>
<constructor-arg>
<bean class="org.opensaml.util.resource.ClasspathResource">
<constructor-arg value="/metadata/wso2idp_metadata.xml"/>
</bean>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
</bean>
</constructor-arg>
</bean>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
<constructor-arg>
<bean class="org.opensaml.saml2.metadata.provider.ResourceBackedMetadataProvider">
<constructor-arg>
<bean class="java.util.Timer"/>
</constructor-arg>
<constructor-arg>
<bean class="org.opensaml.util.resource.ClasspathResource">
<constructor-arg value="/metadata/ssocircleidp_metadata.xml"/>
</bean>
</constructor-arg>
<property name="parserPool" ref="parserPool"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
</bean>
</constructor-arg>
</bean>
</list>
</constructor-arg>
对于生产,我们希望能够将我们的IdP元数据存储在一个数据库中(位于中央)。我希望能够添加、删除和修改元数据,而无需重新部署WAR或重启html" target="_blank">服务器。最初,我认为我可以覆盖CachingMetadataManager,并定义一个可以动态加载所有元数据提供程序的noarg构造函数,但这是不可能的,因为CachingMetadataManager只定义了一个必须接受MetadataProvider列表的构造函数。我最终做了以下事情:
<bean id="metadataList" class="org.arbfile.util.security.saml.DBMetadataProviderList">
<constructor-arg ref="parserPool" />
<constructor-arg>
<bean class="java.util.Timer"/>
</constructor-arg>
</bean>
<bean id="metadata" class="org.springframework.security.saml.metadata.CachingMetadataManager">
<constructor-arg ref="metadataList" />
</bean>
Bean metadataList 可以简单地定义为:
public final class DBMetadataProviderList extends ArrayList<MetadataProvider>
{
private final static Logger log = LoggerFactory.getLogger(DBMetadataProviderList.class);
private ParserPool parser;
public DBMetadataProviderList(ParserPool _parser, Timer _timer) throws MetadataProviderException
{
this.parser = _parser;
// Lookup metadata from DB
}
}
这确实允许我动态读取 IdP 元数据。不过,在刷新方面,我的逻辑就崩溃了。我在Spring论坛上找到了这篇文章,但是它已经3到4岁了。动态读取、添加和更新 IdP 元数据、缓存 IdP 元数据以及按某个时间间隔刷新缓存的最佳方式是什么?在我的例子中,数据库表中的 1 行相当于单个 IdP 元数据定义。
在阅读了几篇文章并扫描了源代码之后,我发现这个问题的答案比我想象的要复杂得多。实际上有3种不同的情况需要解决。
我将一次承担其中的每一个。第1项:可能有几种方法可以解决这个问题,但回顾上面的DBMetadataProviderList
类(在我的OP中)作为快速而肮脏的解决方案。下面是更完整的构造函数代码:
//This constructor allows us to read in metadata stored in a database.
public DBMetadataProviderList(ParserPool _parser, Timer _timer) throws MetadataProviderException
{
this.parser = _parser;
List<String> metadataProviderIds = getUniqueEntityIdListFromDB();
for (final String mdprovId : metadataProviderIds)
{
DBMetadataProvider metadataProvider = new DBMetadataProvider(_timer, mdprovId);
metadataProvider.setParserPool(this.parser);
metadataProvider.setMaxRefreshDelay(480000); // 8 mins (set low for testing)
metadataProvider.setMinRefreshDelay(120000); // 2 mins
ExtendedMetadataDelegate md = new ExtendedMetadataDelegate(metadataProvider, new ExtendedMetadata());
add(md);
}
}
为了解决第二个问题,我使用了< code > FilesystemMetadataProvider 作为指导,并创建了一个< code > dbmetadatprovider 类。通过扩展< code > AbstractReloadingMetadataProvider 类并实现< code>fetchMetadata()方法,我们借助opensaml实现了内置缓存刷新。以下是重要的部分(仅示例代码):
public class DBMetadataProvider extends AbstractReloadingMetadataProvider
{
private String metaDataEntityId; // unique Id for DB lookups
/**
* Constructor.
* @param entityId the entity Id of the metadata. Use as key to identify a database row.
*/
public DBMetadataProvider(String entityId)
{
super();
setMetaDataEntityId(entityId);
}
/**
* Constructor.
* @param backgroundTaskTimer timer used to refresh metadata in the background
* @param entityId the entity Id of the metadata. Use as key to identify a database row.
*/
public DBMetadataProvider(Timer backgroundTaskTimer, String entityId)
{
super(backgroundTaskTimer);
setMetaDataEntityId(entityId);
}
public String getMetaDataEntityId() { return metaDataEntityId; }
public void setMetaDataEntityId(String metaDataEntityId){ this.metaDataEntityId = metaDataEntityId; }
@Override
protected String getMetadataIdentifier() { return getMetaDataEntityId(); }
// This example code simply does straight JDBC
@Override
protected byte[] fetchMetadata() throws MetadataProviderException
{
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try
{
conn = JDBCUtility.getConnection();
ps = conn.prepareStatement("select bla bla bla ENTITY_ID = ?");
ps.setString(1, getMetaDataEntityId());
rs = ps.executeQuery();
if (rs.next())
{
// include a modified date column in schema so that we know if row has changed
Timestamp sqldt = rs.getTimestamp("MOD_DATE"); // use TimeStamp here to get full datetime
DateTime metadataUpdateTime = new DateTime(sqldt.getTime(), ISOChronology.getInstanceUTC());
if (getLastRefresh() == null || getLastUpdate() == null || metadataUpdateTime.isAfter(getLastRefresh()))
{
log.info("Reading IdP metadata from database with entityId = " + getMetaDataEntityId());
Clob clob = rs.getClob("XML_IDP_METADATA");
return clob2Bytes(clob);
}
return null;
}
else
{
// row was not found
throw new MetadataProviderException("Metadata with entityId = '" + getMetaDataEntityId() + "' does not exist");
}
}
catch (Exception e)
{
String msg = "Unable to query metadata from database with entityId = " + getMetaDataEntityId();
log.error(msg, e);
throw new MetadataProviderException(msg, e);
}
finally
{
// clean up connections
}
}
}
这个资源帮助我获得了缓存重新加载元数据提供程序类的正确技术。最后,第#3项可以通过实现这篇文章来解决。
我正在集成spring security saml扩展以支持我的web应用程序中的SSO,我的应用程序应允许不同的客户将其IDP元数据和证书添加到我的webapp(这是一个SP),以便我的webapp可以针对其IDP启动SSO。 现在我正在我的java配置中定义一个“元数据”bean,在其中我将idp元数据添加到CachingMetadataManager。但是这种情况只发生一次,我无法弄清楚如何
Java类: 应用yml公司 应用程序模拟ecom。yml公司 当我击中时,http://localhost:8080/hello,我得到的回应是“Hello mock api.com!”。 如果我从应用程序中删除模拟的ecom。然后调用刷新后api调用http://localhost:8080/refresh要刷新上下文,我希望得到“Hello dev api.com!”但我收到了“你好,moc
我在这个JTable上有问题。我这样编辑单元格 然后,我按Enter键提交更改。在这里,我希望gui用新的值刷新表。 但它们不显示,只有当我像这样更改选择时它们才显示 这是在TableModel中调用的。
在阅读如何在运行时访问元组元素时,我想到了以下使用运行时索引获取元组元素的实现 我自己用GCC11.2试过了。我调用了API来检索元组,但出现了以下错误 找到下面的代码(实时演示)
我们正在使用keyclope身份代理将身份验证联合到外部IDP。标识提供程序的类型为OpenID Connect v1.0。此外,我们正在PKCE中使用OIDC授权代码流。 我们能够根据以下留档成功地从外部IDP中检索令牌:https://www.keycloak.org/docs/latest/server_admin/#retrieving-external-idp-tokens 但是,当使用
官方记录说 写入易失性字段与监视器释放具有相同的记忆效果,从易失性字段读取与监视器获取具有相同的记忆效果。 和 有效地,挥发性的语义学得到了实质性的加强,几乎达到了同步的水平。为了可见性的目的,挥发性字段的每次读取或写入都像“半”次同步。 从这里开始。 这是否意味着,对volatile变量的任何写入都会使执行线程将其缓存刷新到主存中,而每次从volatile字段读取都会使线程从主存重新读取其变量?