处理UserRedirectRequiredException(需要重定向才能获得用户批准) [英] Handle UserRedirectRequiredException (A redirect is required to get the users approval)

查看:1869
本文介绍了处理UserRedirectRequiredException(需要重定向才能获得用户批准)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一周前,我开始使用OAuth2框架(使用Spring Boot v1.3.0.M4)开发应用程序.对我来说是全新的体验.因此,我尝试使其尽可能简单以更好地理解它.我正在使用Spring Security OAuth2,并且在正确使用它方面遇到困难.

One week ago, I began the development of an application using the OAuth2 framework (with Spring Boot v1.3.0.M4). A brand new experience for me. So I try to make it as simple as possible to understand it better. I am using Spring Security OAuth2 and I am facing difficulties to use it correctly.

我想做什么

What I want to do

在此用户授权我的应用程序时对用户进行身份验证.实际上,我不希望他在我的应用程序上注册,因此他可以自由地使用它,而不必填写无聊的表格来注册.

Authenticate a user when this one authorize my application. Actually, I don't want him to register on my application so he can freely use it without having to fill boring forms to register.

遇到的问题

Problem encountered

我找不到处理UserRedirectRequired异常的方法.因为我不这样做,所以永远不会将用户重定向到授权页面,并且会引发(并且未处理)异常.

I can't find a way to handle UserRedirectRequired Exception. Because I don't do it, the user is never redirected to the authorization page and an exception is thrown (and unhandled).

StandardController.java

StandardController.java

package org.test.oauth.web;

import java.security.Principal;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class StandardController {

    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String getHelloWorld() {
        return "Hello world !";
    }

    @RequestMapping(value = "/user", method = RequestMethod.GET)
    public Principal getUser(Principal principal) {
        return principal;
    }
}

StandardConfiguration.java

StandardConfiguration.java

package org.test.oauth.configuration;

import java.util.Arrays;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.filter.OAuth2ClientContextFilter;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
import org.springframework.security.web.access.ExceptionTranslationFilter;

@Configuration
@EnableOAuth2Sso
public class StandardConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private OAuth2ClientContextFilter oauth2ClientContextFilter;

    @Autowired
    private OAuth2ClientContext oauth2ClientContext;


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http
        .authorizeRequests().antMatchers("/login").anonymous().and()
        .authorizeRequests().anyRequest().authenticated().and()
        .httpBasic().and()
        .addFilterAfter(oauth2ClientContextFilter, ExceptionTranslationFilter.class);
        // @formatter:on
    }

//  org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.security.oauth2.client.OAuth2RestOperations] is defined: expected single matching bean but found 2: restTemplate,userInfoRestTemplate
//  @Bean
//  public OAuth2RestOperations restTemplate() {
//      return new OAuth2RestTemplate(bnetResource(), oauth2ClientContext);
//  }

    @Bean
    public OAuth2ProtectedResourceDetails bnetResource() {
        AuthorizationCodeResourceDetails resource = new AuthorizationCodeResourceDetails();
        resource.setId("bnet");
        resource.setClientId("***");
        resource.setClientSecret("***");
        resource.setAccessTokenUri("https://eu.battle.net/oauth/token");
        resource.setUserAuthorizationUri("https://eu.battle.net/oauth/authorize");
        resource.setScope(Arrays.asList("wow.profile"));
        return resource;
    }
}


我的问题

当我进入我的根应用程序时,由于我未通过身份验证,Spring Security会将我重定向.它将我重定向到登录页面. Spring Boot默认配置会引发和处理许多异常,但是当创建并引发UserRedirectRequiredException时,没有过滤器会处理它.在调试应用程序时,我发现我的oauth2ClientContextFilter发现的最后一个异常是AccessDeniedException.我怀疑我的过滤器(实际上是默认配置中的OAuth2ClientContextFilter)在过滤器链中设置不正确.


My problem

When I get on my root application, Spring Security redirects me as I am not authenticated. It redirects me to the login page. Many exceptions are thrown and handled by the Spring Boot default configuration but when the UserRedirectRequiredException is created and thrown, no filter handles it. Debugging my application, I found that the last exception found by my oauth2ClientContextFilter is AccessDeniedException. I doubt that my filter (which is actually the OAuth2ClientContextFilter from the default configuration) is not correctly set in the filter chain.

Stacktrace

Stacktrace

org.springframework.security.oauth2.client.resource.UserRedirectRequiredException: A redirect is required to get the users approval
    at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.getRedirectForAuthorization(AuthorizationCodeAccessTokenProvider.java:347) ~[spring-security-oauth2-2.0.7.RELEASE.jar:na]
    at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.obtainAccessToken(AuthorizationCodeAccessTokenProvider.java:194) ~[spring-security-oauth2-2.0.7.RELEASE.jar:na]
    at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:221) ~[spring-security-oauth2-2.0.7.RELEASE.jar:na]
    at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:173) ~[spring-security-oauth2-2.0.7.RELEASE.jar:na]
    at org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter.attemptAuthentication(OAuth2ClientAuthenticationProcessingFilter.java:94) ~[spring-security-oauth2-2.0.7.RELEASE.jar:na]
    at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:217) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:120) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:96) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:91) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:53) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176) ~[spring-security-web-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) ~[tomcat-embed-core-8.0.23.jar:8.0.23]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) ~[tomcat-embed-core-8.0.23.jar:8.0.23]
    at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87) ~[spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]

看着堆栈跟踪,我试图更改过滤器链中过滤器的顺序.因此,我尝试将OAuth2ClientContextFilter放在OAuth2ClientAuthenticationProcessingFilter之后.不幸的是,当我启动该应用程序时,发生错误,告诉我该过滤器未注册.

Looking at the stacktrace, I tried to change the order of my filter in the filter chain. So I tried to put my OAuth2ClientContextFilter after the OAuth2ClientAuthenticationProcessingFilter. Unfortunately, when I launch the application, an error occurs telling me that the filter is unregistered.

更改

Change

.addFilterAfter(oauth2ClientContextFilter, ExceptionTranslationFilter.class);

.addFilterAfter(oauth2ClientContextFilter, OAuth2ClientAuthenticationProcessingFilter.class);

Stacktrace

Stacktrace

2015-08-25 12:05:50.990 ERROR 9132 --- [ost-startStop-1] o.s.b.c.embedded.tomcat.TomcatStarter    : Error starting Tomcat context: org.springframework.beans.factory.UnsatisfiedDependencyException
2015-08-25 12:05:51.054  WARN 9132 --- [           main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt
java.lang.IllegalArgumentException: Cannot register after unregistered Filter class org.springframework.security.oauth2.client.filter.OAuth2ClientAuthenticationProcessingFilter
    at org.springframework.security.config.annotation.web.builders.FilterComparator.registerAfter(FilterComparator.java:145) ~[spring-security-config-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.springframework.security.config.annotation.web.builders.HttpSecurity.addFilterAfter(HttpSecurity.java:960) ~[spring-security-config-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at org.test.oauth.configuration.StandardConfiguration.configure(StandardConfiguration.java:36) ~[classes/:na]
    at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.getHttp(WebSecurityConfigurerAdapter.java:199) ~[spring-security-config-4.0.2.RELEASE.jar:4.0.2.RELEASE]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_45]

因此,我请您帮助我解决此问题并摆脱此问题.我知道关于此问题有很多问题已得到解答,但并不能如愿地帮助我.

So I ask you to help me getting through this and get rid of this problem. I am aware that there are a lot of questions about this issue that are already answered but it couldn't help me as wanted.

感谢您在帮助我上所花费的时间.

Thanking you for the time dedicated you took to help me.

塞德里克

推荐答案

下面是@Stilleur解决方案的替代方法.它在Spring官方指南中的处理重定向"标题下建议: https://spring.io/guides/tutorials/spring-boot-oauth2/

An alternative to @Stilleur's solution is below. It is suggested in an official Spring guide under the heading "Handling the Redirects": https://spring.io/guides/tutorials/spring-boot-oauth2/

@Bean
public FilterRegistrationBean oauth2ClientFilterRegistration(
    OAuth2ClientContextFilter filter) {
  FilterRegistrationBean registration = new FilterRegistrationBean();
  registration.setFilter(filter);
  registration.setOrder(-100);
  return registration;
}

这篇关于处理UserRedirectRequiredException(需要重定向才能获得用户批准)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆