我的应用程序有一个单一的endpoint。它触发OAuth2授权授予流。它只能由匿名用户调用。每个匿名用户代表在资源服务器中具有不同权限的不同人员。需要每个匿名用户的同意(即不同的授权)。
Spring Boot OAuth2中需要每个匿名用户同意的配置是什么?
我正在使用Spring Boot oath2-Client 2.6.4和Spring Security 5.6.2。
目前,我有oauth2client配置。它不符合要求。在此配置中,只请求一次同意,并将其应用于以下所有匿名呼叫者。所有呼叫者共享相同的授权和访问令牌。
我觉得oauth2login可能是合适的配置,但在尝试oauth2login之前,我必须克服一些必要的定制。我必须禁用生成的登录页面,该页面提示用户选择提供者,并且我必须向授权请求中添加自定义字段。我在outh2login中的这些定制没有成功。因此,这种方法感觉不错,但似乎不可用。
有关此endpoint调用者的信息,请参阅:HL7 FHIR SMART-APP-LAUNCH
这方面存在许多挑战,涉及:
我的应用程序有一个单一的endpoint。[...]它只能由匿名用户调用。
这一要求使得Spring Security很难提供太多帮助。这是因为匿名用户通常没有会话,授权代码授予是一个需要状态的流,因此需要会话。顺便说一句,我不确定我是否完全理解您链接到的规范(据我所知,它构建在OAuth 2.0上)在允许匿名用户的客户端环境中是如何或为什么有意义的。
尽管如此,这似乎只需要使用<代码>。如果您创建用于管理匿名用户的自定义过滤器,则oauth2Client()支持Spring Security。注意:以下假设即使浏览器中存在会话,授权服务器也不会忽略启动参数。
以下配置定义和配置此过滤器,以及自定义oauth2Client()以将启动参数传递给授权服务器。它本质上为启动参数创建了一个临时身份验证,该参数将在流期间保存为会话中的principalName。
@EnableWebSecurity
public class SecurityConfig {
private static final String PARAMETER_NAME = "launch";
private static final String ROLE_NAME = "LAUNCH_USER";
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, ClientRegistrationRepository clientRegistrationRepository) throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().hasRole(ROLE_NAME)
)
.addFilterAfter(authenticationFilter(), AnonymousAuthenticationFilter.class)
.oauth2Client((oauth2) -> oauth2
.authorizationCodeGrant((authorizationCode) -> authorizationCode
.authorizationRequestResolver(authorizationRequestResolver(clientRegistrationRepository))
)
);
return http.build();
}
private OAuth2AuthorizationRequestResolver authorizationRequestResolver(ClientRegistrationRepository clientRegistrationRepository) {
DefaultOAuth2AuthorizationRequestResolver authorizationRequestResolver =
new DefaultOAuth2AuthorizationRequestResolver(clientRegistrationRepository, OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI);
// Configure a request customizer for the OAuth2AuthorizationRequestRedirectFilter
authorizationRequestResolver.setAuthorizationRequestCustomizer((authorizationRequest) -> {
Authentication currentAuthentication = SecurityContextHolder.getContext().getAuthentication();
// Customize request with principal name originally obtained from request parameter
if (currentAuthentication instanceof RequestParameterAuthenticationToken) {
Map<String, Object> additionalParameters = Map.of(PARAMETER_NAME, currentAuthentication.getName());
authorizationRequest.additionalParameters(additionalParameters);
}
});
return authorizationRequestResolver;
}
private RequestParameterAuthenticationFilter authenticationFilter() {
return new RequestParameterAuthenticationFilter(PARAMETER_NAME, AuthorityUtils.createAuthorityList("ROLE_" + ROLE_NAME));
}
/**
* Authentication filter that authenticates an anonymous request using a request parameter.
*/
public static final class RequestParameterAuthenticationFilter extends OncePerRequestFilter {
private final String parameterName;
private final List<GrantedAuthority> authorities;
public RequestParameterAuthenticationFilter(String parameterName, List<GrantedAuthority> authorities) {
this.parameterName = parameterName;
this.authorities = authorities;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
SecurityContext existingSecurityContext = SecurityContextHolder.getContext();
if (existingSecurityContext != null && !(existingSecurityContext.getAuthentication() instanceof AnonymousAuthenticationToken)) {
filterChain.doFilter(request, response);
return;
}
String principalName = request.getParameter(parameterName);
if (principalName != null) {
Authentication authenticationResult = new RequestParameterAuthenticationToken(principalName, authorities);
authenticationResult.setAuthenticated(true);
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
securityContext.setAuthentication(authenticationResult);
SecurityContextHolder.setContext(securityContext);
}
filterChain.doFilter(request, response);
}
}
/**
* Custom authentication token that can be persisted between requests, but is otherwise very similar to
* {@link AnonymousAuthenticationToken}.
*/
public static final class RequestParameterAuthenticationToken extends AbstractAuthenticationToken implements Serializable {
private static final long serialVersionUID = 1L;
private final String principalName;
public RequestParameterAuthenticationToken(String principalName, Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principalName = principalName;
}
@Override
public Object getPrincipal() {
return this.principalName;
}
@Override
public Object getCredentials() {
return this.principalName;
}
}
}
您可以在控制器endpoint中使用它,如以下示例所示:
java prettyprint-override">@RestController
public class LaunchController {
@GetMapping("/app/launch")
public void launch(
@RegisteredOAuth2AuthorizedClient("fhir-client")
OAuth2AuthorizedClient authorizedClient) {
String launchParameter = authorizedClient.getPrincipalName();
String accessToken = authorizedClient.getAccessToken().getTokenValue();
// Use authorizedClient.getAccessToken() to make a request (WebClient)...
// Clear the SecurityContext after the request, to force the next request
// to start the flow over again
SecurityContextHolder.clearContext();
}
}
有关此答案的其他上下文,请参阅相关问题#11069。
Parse将在年底关闭,所以我决定开始使用Firebase。我需要用3个字段实现注册过程:电子邮件、用户名、密码(电子邮件 由于Firebase没有提供像Parse这样管理用户名的简单方法,我决定只使用电子邮件/密码注册并保存一些附加数据,例如用户名。这是我的用户数据结构: 但是,我想做的是使用户名唯一,并在创建帐户之前进行检查。以下是我的规则: 非常感谢您的帮助
我正在使用SoapUI的开源版本进行一些SOAP Web服务负载测试。 我希望每个请求与以前的请求尽可能不同,我不希望使用相同的属性进行负载测试。 我有一个属性文件,它有几个属性,每个属性值都调用groovy脚本从文件中读取一个随机值,并将其分配给测试用例属性,即在值字段中: <代码>${=(DynamicPropertyScript)} 脚本: 如果我在测试用例开始时调用这个脚本,那么这个脚本工
问题内容: 我正在使用任何具有唯一性的应用程序,每当最终用户输入他的应用程序时,我都会通过Ajax发出SQL查询,以检查是否存在该查询。在此之前,它工作正常,但现在我知道那是什么时候存在,那么我想在JSP页面上显示该ID已被使用,反之亦然。 所以我的问题是如何从struts应用程序获取响应并将其提供给Ajax或JSP页面,以及在“ struts.xml”结果标签中写入什么? 这是我的Ajax呼叫:
我有一个注册表格,通过以下步骤: 填写用户信息(姓名,地址等)和用户名 如果用户按下提交按钮,则检查用户名是否已经在数据库中 如果用户名已经在使用,他必须重命名用户名,如果没有,则显示他输入的内容(名称,地址等)。 他必须确认网站规则和他输入的数据是正确的。如果他按下确认按钮,数据库中将插入一行他的详细信息和用户名。 我不想在步骤2之后将行插入数据库中。,因为我不希望数据库中没有确认规则的用户的行
每当我试图进入我的repo-git时,它都会同时请求
在上面的代码示例中,试图为每个请求生成唯一的txn-id。但是,观察到它正在重复使用相同的数字导致重复。我还尝试使用以下方法根据当前时间生成,当在1秒内触发超过1个请求时,它仍然会导致重复。 任何替代解决方案来为每个请求生成唯一ID,而不管并发情况如何? 提前感谢。