gpt4 book ai didi

java - 如何使用动态 URL 匹配器配置配置 Spring security Oauth 2.0?

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:37:26 27 4
gpt4 key购买 nike

我需要在带有远程授权服务器的 spring boot oauth 2.0 资源服务器中实现动态 spring 安全匹配器(URL、方法、角色、权限等)验证。

有没有关于如何将这些信息提取到数据库的提示?

到目前为止,我发现了一个关于如何继续的小指示,创建一个过滤器扩展 DefaultFilterInvocationSecurityMetadataSource 并覆盖方法 getAttributes(Object object),但我没有知道这是否是最好的方法。 https://github.com/sohamghosh/spring-security-dynamic-roles

最佳答案

我使用我随问题发布的链接所指示的想法来完成我的解决方案。如果有人可以给我提示,我将不胜感激。

首先,我希望权限仅在我的资源服务器上与用户相关联,因为我的授权服务器没有一切也不需要现在我的应用程序业务规则、角色和权限。此外,我想将这些 Authorities 存储在数据库中,以便我可以对其进行动态管理。因此,我创建了一个自定义 accessTokenConverter 以链接到我的 RemoteTokenServices(指向我的 Oauth 2.0 Authorization Server),它覆盖了 extractAuthentication 方法 DefaultAccessTokenConverter 添加这些新的 Authorities。请参阅下面的完整类配置。

    /**
* Class responsible for configuring Resource Server's security filters and connectivity with Heimdall (Authorization Server)
* @author mariane.vieira
*
*/
@Configuration
@EnableResourceServer
public class OAuth2ResourceConfig extends ResourceServerConfigurerAdapter {
@Value("${auth.server.resourceId}")
private String resourceId;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DynamicAuthorityRepository authorityRepository;
@Autowired
private UrlInterceptorRepository urlInterceptorRepository;
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(resourceId).stateless(false);
}

@Override
public void configure(HttpSecurity http) throws Exception {
http
// Since we want the protected resources to be accessible in the UI as well we need
// session creation to be allowed (it's disabled by default in 2.0.6)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.addFilter(filterSecurityInterceptor())
//permitting all because security paths verifications are going to be dynamic
//because of this filter above
.authorizeRequests().antMatchers("/**").permitAll();
}

/**
* Dynamic {@link AccessTokenConverter}, normaly extracts authentication just like
* {@link DefaultAccessTokenConverter} but fetches others authorities localy stored
* with {@link DynamicAuthorityRepository} by username.
*
* @author mariane.vieira
*
*/
public class DynamicAccessTokenConverter extends DefaultAccessTokenConverter {
@Override
public OAuth2Authentication extractAuthentication(Map<String, ?> map) {
OAuth2Authentication authentication = super.extractAuthentication(map);

List<DynamicAuthority> dynamicAuthorities = authorityRepository.findByUsername(String.valueOf(authentication.getPrincipal()));

List<GrantedAuthority> authorities = authentication.getAuthorities().stream().collect(Collectors.toList());
authorities.addAll(dynamicAuthorities.stream().map(auth -> new SimpleGrantedAuthority(auth.getAuthority()))
.collect(Collectors.toList()));

OAuth2Request request = new OAuth2Request(authentication.getOAuth2Request().getRequestParameters(),
authentication.getOAuth2Request().getClientId(), authorities, true,
authentication.getOAuth2Request().getScope(), authentication.getOAuth2Request().getResourceIds(),
null, null, null);

return new OAuth2Authentication(request,
new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), "N/A", authorities));
}
}
/**
* Instantiates Bean accessTokenConverter as an instance of {@link DynamicAccessTokenConverter}
* @return {@link DynamicAccessTokenConverter}
*/
@Bean
public AccessTokenConverter accessTokenConverter() {
return new DynamicAccessTokenConverter();
}

/**
* Instantiates Bean remoteTokenServices with informations of Heimdall (Authorization Server) instance and
* client credentials. Besides, sets our custom accessTokenConverter to fetch authorities dynamically.
* @param checkTokenUrl Url to Heimdall's (Authorization Server) check token endpoint
* @param clientId Client Id registered in Heimdall (Authorization Server)
* @param clientSecret Client Secret registered in Heimdall (Authorization Server)
* @return {@link RemoteTokenServices} bean
*/
@Bean
public RemoteTokenServices remoteTokenServices(final @Value("${auth.server.url}") String checkTokenUrl,
final @Value("${auth.server.clientId}") String clientId,
final @Value("${auth.server.clientsecret}") String clientSecret) {
final RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
remoteTokenServices.setCheckTokenEndpointUrl(checkTokenUrl);
remoteTokenServices.setClientId(clientId);
remoteTokenServices.setClientSecret(clientSecret);
remoteTokenServices.setAccessTokenConverter(accessTokenConverter());
return remoteTokenServices;
}

/**
* Instantiates Bean remoteTokenServices filterSecurityInterceptor, instance of {@link DynamicFilterInvocationSecurityMetadataSource}
* that intercepts every request to verify security rules. These rules are stored in database and can be formed and verified
* dynamically.
* @return {@link FilterSecurityInterceptor} Bean, instance of {@link DynamicFilterInvocationSecurityMetadataSource}
*/
public FilterSecurityInterceptor filterSecurityInterceptor(){
DynamicFilterInvocationSecurityMetadataSource dynamicFilter = new DynamicFilterInvocationSecurityMetadataSource(
new LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>>());
dynamicFilter.setUrlInterceptorRepository(urlInterceptorRepository);
FilterSecurityInterceptor filter = new FilterSecurityInterceptor();
filter.setAuthenticationManager(authenticationManager);
filter.setAccessDecisionManager(accessDecisionManager());
filter.setSecurityMetadataSource(dynamicFilter);
return filter;
}

/**
* Instantiates Bean accessDecisionManager, instance of {@link UnanimousBased} with {@link ScopeVoter}, {@link RoleVoter}
* and {@link AuthenticatedVoter}.
* @return {@link AccessDecisionManager} bean, instance of {@link UnanimousBased}
*/
@Bean
public AccessDecisionManager accessDecisionManager(){
return new UnanimousBased(Arrays.asList(new ScopeVoter(), new RoleVoter(), new AuthenticatedVoter()));
}
}

此外,如上所述,我还想动态验证安全路径访问并将其存储在数据库中。我添加了一个 FilterSecurityInterceptor 和我个性化的安全元数据源。它由上面的配置类实例化。下面的类是安全元数据源,适用于在数据库中搜索路径及其ConfigAttributes

public class DynamicFilterInvocationSecurityMetadataSource extends DefaultFilterInvocationSecurityMetadataSource {

private UrlInterceptorRepository urlInterceptorRepository;

public DynamicFilterInvocationSecurityMetadataSource(LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap) {
super(requestMap);
}

public UrlInterceptorRepository getUrlInterceptorRepository() {
return urlInterceptorRepository;
}

public void setUrlInterceptorRepository(UrlInterceptorRepository urlInterceptorRepository) {
this.urlInterceptorRepository = urlInterceptorRepository;
}

/**
* {@link ConfigAttribute} with specific attribute (access rule).
* Possible values to getAttribute's return:
* - IS_AUTHENTICATED_ANONYMOUSLY - No token in the request
* - IS_AUTHENTICATED_REMEMBERED
* - IS_AUTHENTICATED_FULLY - With a valid token
* - SCOPE_<scope> - Token with a specific scope
* - ROLE_<role> - Token's user with specific role
* @author mariane.vieira
*
*/
public class DynamicConfigAttribute implements ConfigAttribute {
private static final long serialVersionUID = 1201502296417220314L;
private String attribute;
public DynamicConfigAttribute(String attribute) {
this.attribute = attribute;
}
@Override
public String getAttribute() {
/* Possible values to getAttribute's return:
* IS_AUTHENTICATED_ANONYMOUSLY, IS_AUTHENTICATED_REMEMBERED
* IS_AUTHENTICATED_FULLY, SCOPE_<scope>, ROLE_<role>
*/
return this.attribute;
}
@Override
public String toString() {
return this.attribute;
}
}

@Override
public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
FilterInvocation fi = (FilterInvocation) object;
String url = fi.getRequestUrl();
String httpMethod = fi.getRequest().getMethod();

if (url != null) {
//Searches for interceptors whose patterns matches the URL
List<UrlInterceptor> interceptors = this.urlInterceptorRepository.findByUrl(url);

Collection<ConfigAttribute> configAttributes = interceptors.stream()
//If the httpMethod is null is because it is valid for all methods
.filter(in -> in.getHttpMethod() == null || in.getHttpMethod().equals(httpMethod))
.map(in -> new DynamicConfigAttribute(in.getAccess()))
.collect(Collectors.toList());

return configAttributes;
}
return null;
}

@Override
public Collection<ConfigAttribute> getAllConfigAttributes() {
return null;
}

@Override
public boolean supports(Class<?> clazz) {
return FilterInvocation.class.isAssignableFrom(clazz);
}
}

关于java - 如何使用动态 URL 匹配器配置配置 Spring security Oauth 2.0?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39394900/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com