- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
用于多因素身份验证的Spring OAuth2实现的完整代码已上传到a file sharing site that you can download by clicking on this link。以下说明说明了如何使用链接在任何计算机上重新创建当前问题。 提供500点奖励。
当前错误:
当用户尝试使用the Spring Boot OAuth2 app from the link in the preceding paragraph中的两因素身份验证进行身份验证时,将触发错误。当应用程序应在第二页上请求用户提供用于确认用户身份的个人识别码时,便会在该过程中抛出该错误。
鉴于空客户端正在触发此错误,问题似乎出在Spring Boot OAuth2中如何将ClientDetailsService
连接到Custom OAuth2RequestFactory
。
entire debug log can be read at a file sharing site by clicking on this link。日志中的完整堆栈跟踪仅包含对应用程序中实际代码的一个引用,该行代码为:
AuthorizationRequest authorizationRequest =
oAuth2RequestFactory.createAuthorizationRequest(paramsFromRequest(request));
org.springframework.security.oauth2.provider.NoSuchClientException:
No client with requested id: null
/oauth/authorize
端点,然后2.)通过/oauth/authorize
返回TwoFactorAuthenticationController
端点。
NoSuchClientException
,同时还演示了已在
ROLE_TWO_FACTOR_AUTHENTICATED
中成功为客户端授予了
POST /secure/two_factor_authenticated
。鉴于后续步骤很简单,只要用户以成功完成
的所有工件输入 SECOND PASS ,就可以将流程明显地打断到CustomOAuth2RequestFactory
中的 SECOND PASS 条目中FIRST PASS 。只要我们在这里成功解决了
FIRST PASS ,
SECOND PASS 可以是一个单独的问题。
AuthorizationServerConfigurerAdapter
的代码,我尝试在其中建立连接:
@Configuration
@EnableAuthorizationServer
protected static class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired//ADDED AS A TEST TO TRY TO HOOK UP THE CUSTOM REQUEST FACTORY
private ClientDetailsService clientDetailsService;
@Autowired//Added per: https://stackoverflow.com/questions/30319666/two-factor-authentication-with-spring-security-oauth2
private CustomOAuth2RequestFactory customOAuth2RequestFactory;
//THIS NEXT BEAN IS A TEST
@Bean CustomOAuth2RequestFactory customOAuth2RequestFactory(){
return new CustomOAuth2RequestFactory(clientDetailsService);
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
KeyPair keyPair = new KeyStoreKeyFactory(
new ClassPathResource("keystore.jks"), "foobar".toCharArray()
)
.getKeyPair("test");
converter.setKeyPair(keyPair);
return converter;
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("acme")//API: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/config/annotation/builders/ClientDetailsServiceBuilder.ClientBuilder.html
.secret("acmesecret")
.authorizedGrantTypes("authorization_code", "refresh_token", "password")
.scopes("openid");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints//API: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerEndpointsConfigurer.html
.authenticationManager(authenticationManager)
.accessTokenConverter(jwtAccessTokenConverter())
.requestFactory(customOAuth2RequestFactory);//Added per: https://stackoverflow.com/questions/30319666/two-factor-authentication-with-spring-security-oauth2
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer//API: http://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/config/annotation/web/configurers/AuthorizationServerSecurityConfigurer.html
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
}
TwoFactorAuthenticationFilter
的代码,其中包含上面触发错误的代码:
package demo;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.oauth2.provider.AuthorizationRequest;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
import org.springframework.security.web.DefaultRedirectStrategy;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
//This class is added per: https://stackoverflow.com/questions/30319666/two-factor-authentication-with-spring-security-oauth2
/**
* Stores the oauth authorizationRequest in the session so that it can
* later be picked by the {@link com.example.CustomOAuth2RequestFactory}
* to continue with the authoriztion flow.
*/
public class TwoFactorAuthenticationFilter extends OncePerRequestFilter {
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
private OAuth2RequestFactory oAuth2RequestFactory;
//These next two are added as a test to avoid the compilation errors that happened when they were not defined.
public static final String ROLE_TWO_FACTOR_AUTHENTICATED = "ROLE_TWO_FACTOR_AUTHENTICATED";
public static final String ROLE_TWO_FACTOR_AUTHENTICATION_ENABLED = "ROLE_TWO_FACTOR_AUTHENTICATION_ENABLED";
@Autowired
public void setClientDetailsService(ClientDetailsService clientDetailsService) {
oAuth2RequestFactory = new DefaultOAuth2RequestFactory(clientDetailsService);
}
private boolean twoFactorAuthenticationEnabled(Collection<? extends GrantedAuthority> authorities) {
return authorities.stream().anyMatch(
authority -> ROLE_TWO_FACTOR_AUTHENTICATION_ENABLED.equals(authority.getAuthority())
);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// Check if the user hasn't done the two factor authentication.
if (AuthenticationUtil.isAuthenticated() && !AuthenticationUtil.hasAuthority(ROLE_TWO_FACTOR_AUTHENTICATED)) {
AuthorizationRequest authorizationRequest = oAuth2RequestFactory.createAuthorizationRequest(paramsFromRequest(request));
/* Check if the client's authorities (authorizationRequest.getAuthorities()) or the user's ones
require two factor authenticatoin. */
if (twoFactorAuthenticationEnabled(authorizationRequest.getAuthorities()) ||
twoFactorAuthenticationEnabled(SecurityContextHolder.getContext().getAuthentication().getAuthorities())) {
// Save the authorizationRequest in the session. This allows the CustomOAuth2RequestFactory
// to return this saved request to the AuthenticationEndpoint after the user successfully
// did the two factor authentication.
request.getSession().setAttribute(CustomOAuth2RequestFactory.SAVED_AUTHORIZATION_REQUEST_SESSION_ATTRIBUTE_NAME, authorizationRequest);
// redirect the the page where the user needs to enter the two factor authentiation code
redirectStrategy.sendRedirect(request, response,
ServletUriComponentsBuilder.fromCurrentContextPath()
.path(TwoFactorAuthenticationController.PATH)
.toUriString());
return;
}
}
filterChain.doFilter(request, response);
}
private Map<String, String> paramsFromRequest(HttpServletRequest request) {
Map<String, String> params = new HashMap<>();
for (Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
params.put(entry.getKey(), entry.getValue()[0]);
}
return params;
}
}
tar -zxvf oauth2.tar(1).gz
authserver
,然后键入
oauth2/authserver
来启动
mvn spring-boot:run
应用程序。
resource
,然后键入
oauth2/resource
,以启动
mvn spring-boot:run
应用程序
ui
,然后键入
oauth2/ui
来启动
mvn spring-boot:run
应用程序
http : // localhost : 8080
Login
,然后输入
Frodo
作为用户,并输入
MyRing
作为密码,然后单击提交。
这将触发上面显示的错误。
authserver
应用程序中,尤其是在
authserver/src/main/java
和
authserver/src/main/resources/templates
中。
FilterConfigurationBean
,它解决了
NoSuchClientException
。但是OP询问如何通过图中的控制流完成
500点赏金来完成
FIRST PASS 。
ROLE_TWO_FACTOR_AUTHENTICATION_ENABLED
中设置
Users.loadUserByUername()
来缩小问题的范围,如下所示:
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
String password;
List<GrantedAuthority> auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER");
if (username.equals("Samwise")) {//ROLE_TWO_FACTOR_AUTHENTICATION_ENABLED will need to come from the resource, NOT the user
auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_HOBBIT, ROLE_TWO_FACTOR_AUTHENTICATION_ENABLED");
password = "TheShire";
}
else if (username.equals("Frodo")){//ROLE_TWO_FACTOR_AUTHENTICATION_ENABLED will need to come from the resource, NOT the user
auth = AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_HOBBIT, ROLE_TWO_FACTOR_AUTHENTICATION_ENABLED");
password = "MyRing";
}
else{throw new UsernameNotFoundException("Username was not found. ");}
return new org.springframework.security.core.userdetails.User(username, password, auth);
}
/security/two_factor_authentication
的请求。
需要做哪些进一步的更改才能通过控制流完成FIRST PASS,以便POST /secure/two_factor_authentication
可以SYSO ROLE_TWO_FACTOR_AUTHENTICATED
进行?
最佳答案
该项目需要大量的修改才能实现所描述的流程,这超出了单个问题的范围。该答案将仅关注如何解决:
org.springframework.security.oauth2.provider.NoSuchClientException: No client with requested id: null
SecurityWebApplicationInitializer
和
Filter
bean时。
WebApplicationInitializer
instances are not run by Spring Boot。这包括将在部署到独立Servlet容器的WAR中工作的所有
AbstractSecurityWebApplicationInitializer
子类。因此,发生的事情是Spring Boot根据
@Bean
注释创建了过滤器,忽略了
AbstractSecurityWebApplicationInitializer
,并将过滤器应用于所有URL。同时,您只希望将过滤器应用于尝试传递给
addMappingForUrlPatterns
的那些URL。
FilterConfigurationBean
。对于问题中描述的流程,该流程正尝试将自定义
TwoFactorAuthenticationFilter
应用于
/oauth/authorize
,如下所示:
@Bean
public FilterRegistrationBean twoFactorAuthenticationFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(twoFactorAuthenticationFilter());
registration.addUrlPatterns("/oauth/authorize");
registration.setName("twoFactorAuthenticationFilter");
return registration;
}
@Bean
public TwoFactorAuthenticationFilter twoFactorAuthenticationFilter() {
return new TwoFactorAuthenticationFilter();
}
关于spring - OAuth2多重身份验证中的空客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36899386/
我是一名优秀的程序员,十分优秀!