由于cookie冲突(授权代码机制),官方Spring安全性oauth2示例不起作用 [英] Official Spring security oauth2 example doesn't work because of cookies clashing(authorization code mechanism)

查看:741
本文介绍了由于cookie冲突(授权代码机制),官方Spring安全性oauth2示例不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据教程



以下源代码:



SocialApplication.class:

  @SpringBootApplication 
@RestController
@ EnableOAuth2Client
@EnableAuthorizationServer
@Order(200)
公共类SocialApplication扩展WebSecurityConfigurerAdapter {

@Autowired
OAuth2ClientContext oauth2ClientContext;

@RequestMapping({/ user,/ me})
public Map< String,String> user(校长){
Map< String,String> map = new LinkedHashMap<>();
map.put(name,principal.getName());
返回地图;
}

@Override
protected void configure(HttpSecurity http)抛出异常{
// @formatter:off
http.antMatcher(/ * *)。authorizeRequests()。antMatchers(/,/ login **,/ webjars / **)。permitAll()。anyRequest()
.authenticated()。和()。 exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint(/))。和()。logout()
.logoutSuccessUrl(/)。permitAll()。和()。csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())。和()
.addFilterBefore(ssoFilter(),BasicAuthenticationFilter.class);
// @formatter:on
}

@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http)抛出异常{
// @formatter:off
http.antMatcher(/ me)。authorizeRequests()。anyRequest()。authenticated();
// @formatter:on
}
}

public static void main(String [] args){
SpringApplication.run(SocialApplication.class) ,args);
}

@Bean
public FilterRegistrationBean< OAuth2ClientContextFilter> oauth2ClientFilterRegistration(OAuth2ClientContextFilter过滤器){
FilterRegistrationBean< OAuth2ClientContextFilter> registration = new FilterRegistrationBean< OAuth2ClientContextFilter>();
registration.setFilter(filter);
registration.setOrder(-100);
退货登记;
}

@Bean
@ConfigurationProperties(github)
public ClientResources github(){
return new ClientResources();
}

@Bean
@ConfigurationProperties(facebook)
public ClientResources facebook(){
return new ClientResources();
}

private Filter ssoFilter(){
CompositeFilter filter = new CompositeFilter();
列表<过滤器> filters = new ArrayList<>();
filters.add(ssoFilter(facebook(),/ login / facebook));
filters.add(ssoFilter(github(),/ login / github));
filter.setFilters(filters);
返回过滤器;
}

private Filter ssoFilter(ClientResources client,String path){
OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(
path);
OAuth2RestTemplate template = new OAuth2RestTemplate(client.getClient(),oauth2ClientContext);
filter.setRestTemplate(template);
UserInfoTokenServices tokenServices = new UserInfoTokenServices(
client.getResource()。getUserInfoUri(),
client.getClient()。getClientId());
tokenServices.setRestTemplate(template);
filter.setTokenServices(new UserInfoTokenServices(
client.getResource()。getUserInfoUri(),
client.getClient()。getClientId()));
返回过滤器;
}

}

class ClientResources {

@NestedConfigurationProperty
private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();

@NestedConfigurationProperty
private ResourceServerProperties resource = new ResourceServerProperties();

public AuthorizationCodeResourceDetails getClient(){
return client;
}

public ResourceServerProperties getResource(){
return resource;
}
}

index.html:

 <!doctype html> 
< html lang =en>
< head>
< meta charset =utf-8/>
< meta http-equiv =X-UA-Compatiblecontent =IE = edge/>
< title> Demo< / title>
< meta name =descriptioncontent =/>
< meta name =viewportcontent =width = device-width/>
< base href =//>
< link rel =stylesheettype =text / css
href =/ webjars / bootstrap / css / bootstrap.min.css/>
< script type =text / javascriptsrc =/ webjars / jquery / jquery.min.js>< / script>
< script type =text / javascript
src =/ webjars / bootstrap / js / bootstrap.min.js>< / script>
< / head>
< body>
< h1>登录< / h1>
< div class =container unauthenticated>
使用Facebook:< a href =/ login / facebook>点击此处< / a>
< / div>
< div class =container authenticatedstyle =display:none>
登录为:< span id =user>< / span>
< div>
< button onClick =logout()class =btn btn-primary> Logout< / button>
< / div>
< / div>
< script type =text / javascript
src =/ webjars / js-cookie / js.cookie.js>< / script>
< script type =text / javascript>
$ .ajaxSetup({
beforeSend:function(xhr,settings){
if(settings.type =='POST'|| settings.type =='PUT'
|| settings.type =='DELETE'){
if(!(/ ^ http:。* /。test(settings.url)|| /^https:.*/
.test( settings.url))){
//只将令牌发送到相对URL,即本地。
xhr.setRequestHeader(X-XSRF-TOKEN,
Cookies.get('XSRF- TOKEN'));
}
}
}
});
$ .get(/ user,function(data){
$(#user)。html(data.userAuthentication.details.name);
$(。unauthenticated )。hide();
$(。authenticated)。show();
});
var logout = function(){
$ .post(/ logout,function(){
$(#user)。html('');
$(。unauthenticated)。show();
$(。authenticated)。hide();
});
返回true;
}
< / script>
< / body>
< / html>

application.yml:

 服务器:
端口:8080
安全:
oauth2:
客户:
client-id:acme
client-secret:acmesecret
范围:读,写
auto-approve-scopes:'。*'

facebook:
client:
clientId:233668646673605
clientSecret:33b17e044ee6a4fa383f46ec6e28ea1d
accessTokenUri:https://graph.facebook.com/oauth/access_token
userAuthorizationUri:https://www.facebook.com/dialog/oauth
tokenName:oauth_token
authenticationScheme:query
clientAuthenticationScheme:form
resource:
userInfoUri:https://graph.facebook.com/me
github:
客户:
clientId:bd1c0a783ccdd1c9b9e4
clientSecret:1a9030fbca47a5b2c28e92f19050bb77824b5ad1
accessTokenUri:https://github.com/login/oauth/access_token
userAuthorizationUri:https:// github .COM / login / oauth / authorize
clientAuthenticationScheme:form
resource:
userInfoUri:https://api.github.com/user

logging:
level :
org.springframework.security:DEBUG

但是当我打开浏览器并试图点击时 http:// localhost:8080



在浏览器控制台中,我看到:

 (index):44未捕获TypeError:无法读取Object.success中未定义
的属性'详细信息'((索引):44)
at j(jquery.js:3073)
at Object.fireWith [as resolveWith](jquery.js:3185)
at x(jquery.js:8251)
at XMLHttpRequest。<匿名> (jquery.js:8598)

代码:

  $。get(/ user,function(data){
$(#user)。html(data.userAuthentication.details.name);
$(。unauthenticated)。hide();
$(。authenticated)。show();
});

这是因为 / user 响应302状态代码和js回调尝试解析 localhost的结果:8080





我不明白为什么会发生这种重定向。你能解释一下这种行为并帮助修复它吗?



UPDATE



我从 https://github.com/spring-guides/tut-spring-boot-oauth2



重要:



仅在我启动客户端应用程序后重现



PS



如何重现:


要测试新功能,您只需运行这两个应用程序,然后在浏览器中访问
localhost:9999 / client。客户端应用程序将重定向到
本地授权服务器,然后通过Facebook或Github为用户提供通常的
认证选择。一旦这是
完全控制返回到测试客户端,本地访问令牌被授予
并且身份验证完成(您应该在浏览器中看到Hello
消息)。如果您已经使用Github
或Facebook进行了身份验证,您可能甚至没有注意到远程身份验证




答案:



https://stackoverflow.com/a/50349078/2674303

解决方案

最后我发现了问题。我看到这种行为是因为如果你在localhost上启动这两个应用程序,cookie就会发生冲突。



这是因为上下文使用了错误的属性。 / p>

因此,要修复需要更换的应用程序:

  server:
context-path:/ client

with

 服务器:
servlet:
context-path:/ client



PS



我在github上创建了问题:



< a href =https://github.com/spring-guides/tut-spring-boot-oauth2/issues/80 =nofollow noreferrer> https://github.com/spring-guides/tut-spring -boot-oauth2 / issues / 80



并提出拉取请求:



https://github.com/spring-guides/tut-spring- boot-oauth2 / pull / 81



PS2



最后我的拉取请求被合并:
https://github.com/spring-guides/tut-spring-boot-oauth2/pull/81


According the tutorial Spring Boot and OAuth2

I have following project structure:

And following source code:

SocialApplication.class:

@SpringBootApplication
@RestController
@EnableOAuth2Client
@EnableAuthorizationServer
@Order(200)
public class SocialApplication extends WebSecurityConfigurerAdapter {

    @Autowired
    OAuth2ClientContext oauth2ClientContext;

    @RequestMapping({ "/user", "/me" })
    public Map<String, String> user(Principal principal) {
        Map<String, String> map = new LinkedHashMap<>();
        map.put("name", principal.getName());
        return map;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // @formatter:off
        http.antMatcher("/**").authorizeRequests().antMatchers("/", "/login**", "/webjars/**").permitAll().anyRequest()
                .authenticated().and().exceptionHandling()
                .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/")).and().logout()
                .logoutSuccessUrl("/").permitAll().and().csrf()
                .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
                .addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
        // @formatter:on
    }

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
        @Override
        public void configure(HttpSecurity http) throws Exception {
            // @formatter:off
            http.antMatcher("/me").authorizeRequests().anyRequest().authenticated();
            // @formatter:on
        }
    }

    public static void main(String[] args) {
        SpringApplication.run(SocialApplication.class, args);
    }

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

    @Bean
    @ConfigurationProperties("github")
    public ClientResources github() {
        return new ClientResources();
    }

    @Bean
    @ConfigurationProperties("facebook")
    public ClientResources facebook() {
        return new ClientResources();
    }

    private Filter ssoFilter() {
        CompositeFilter filter = new CompositeFilter();
        List<Filter> filters = new ArrayList<>();
        filters.add(ssoFilter(facebook(), "/login/facebook"));
        filters.add(ssoFilter(github(), "/login/github"));
        filter.setFilters(filters);
        return filter;
    }

    private Filter ssoFilter(ClientResources client, String path) {
        OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter(
                path);
        OAuth2RestTemplate template = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);
        filter.setRestTemplate(template);
        UserInfoTokenServices tokenServices = new UserInfoTokenServices(
                client.getResource().getUserInfoUri(),
                client.getClient().getClientId());
        tokenServices.setRestTemplate(template);
        filter.setTokenServices(new UserInfoTokenServices(
                client.getResource().getUserInfoUri(),
                client.getClient().getClientId()));
        return filter;
    }

}

class ClientResources {

    @NestedConfigurationProperty
    private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails();

    @NestedConfigurationProperty
    private ResourceServerProperties resource = new ResourceServerProperties();

    public AuthorizationCodeResourceDetails getClient() {
        return client;
    }

    public ResourceServerProperties getResource() {
        return resource;
    }
}

index.html:

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <title>Demo</title>
    <meta name="description" content=""/>
    <meta name="viewport" content="width=device-width"/>
    <base href="/"/>
    <link rel="stylesheet" type="text/css"
          href="/webjars/bootstrap/css/bootstrap.min.css"/>
    <script type="text/javascript" src="/webjars/jquery/jquery.min.js"></script>
    <script type="text/javascript"
            src="/webjars/bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<h1>Login</h1>
<div class="container unauthenticated">
    With Facebook: <a href="/login/facebook">click here</a>
</div>
<div class="container authenticated" style="display: none">
    Logged in as: <span id="user"></span>
    <div>
        <button onClick="logout()" class="btn btn-primary">Logout</button>
    </div>
</div>
<script type="text/javascript"
        src="/webjars/js-cookie/js.cookie.js"></script>
<script type="text/javascript">
    $.ajaxSetup({
        beforeSend: function (xhr, settings) {
            if (settings.type == 'POST' || settings.type == 'PUT'
                || settings.type == 'DELETE') {
                if (!(/^http:.*/.test(settings.url) || /^https:.*/
                        .test(settings.url))) {
                    // Only send the token to relative URLs i.e. locally.
                    xhr.setRequestHeader("X-XSRF-TOKEN",
                        Cookies.get('XSRF-TOKEN'));
                }
            }
        }
    });
    $.get("/user", function (data) {
        $("#user").html(data.userAuthentication.details.name);
        $(".unauthenticated").hide();
        $(".authenticated").show();
    });
    var logout = function () {
        $.post("/logout", function () {
            $("#user").html('');
            $(".unauthenticated").show();
            $(".authenticated").hide();
        });
        return true;
    }
</script>
</body>
</html>

application.yml:

server:
  port: 8080
security:
  oauth2:
    client:
      client-id: acme
      client-secret: acmesecret
      scope: read,write
      auto-approve-scopes: '.*'

facebook:
  client:
    clientId: 233668646673605
    clientSecret: 33b17e044ee6a4fa383f46ec6e28ea1d
    accessTokenUri: https://graph.facebook.com/oauth/access_token
    userAuthorizationUri: https://www.facebook.com/dialog/oauth
    tokenName: oauth_token
    authenticationScheme: query
    clientAuthenticationScheme: form
  resource:
    userInfoUri: https://graph.facebook.com/me
github:
  client:
    clientId: bd1c0a783ccdd1c9b9e4
    clientSecret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1
    accessTokenUri: https://github.com/login/oauth/access_token
    userAuthorizationUri: https://github.com/login/oauth/authorize
    clientAuthenticationScheme: form
  resource:
    userInfoUri: https://api.github.com/user

logging:
  level:
    org.springframework.security: DEBUG

But when I open browser and try to hit http://localhost:8080

In browser console I see:

(index):44 Uncaught TypeError: Cannot read property 'details' of undefined
    at Object.success ((index):44)
    at j (jquery.js:3073)
    at Object.fireWith [as resolveWith] (jquery.js:3185)
    at x (jquery.js:8251)
    at XMLHttpRequest.<anonymous> (jquery.js:8598)

in code:

$.get("/user", function (data) {
        $("#user").html(data.userAuthentication.details.name);
        $(".unauthenticated").hide();
        $(".authenticated").show();
    });

It happens because /user response with 302 status code and js callback try to parse result of localhost:8080:

I don't understand why this redirect happens. Can you explain this behavior and help to fix it?

UPDATE

I took this code from https://github.com/spring-guides/tut-spring-boot-oauth2

important:

It reproduces only after I start client application.

P.S.

How to reproduce:

To test the new features you can just run both apps and visit localhost:9999/client in your browser. The client app will redirect to the local Authorization Server, which then gives the user the usual choice of authentication with Facebook or Github. Once that is complete control returns to the test client, the local access token is granted and authentication is complete (you should see a "Hello" message in your browser). If you are already authenticated with Github or Facebook you may not even notice the remote authentication

ANSWER:

https://stackoverflow.com/a/50349078/2674303

解决方案

Finally I've found the problem. I see this behaviour due the fact of cookies clashing for client and server if you start both applications on localhost.

It happens due the fact of usage wrong property for context.

So to fix application you need to replace:

server:
  context-path: /client

with

server:  
  servlet:
    context-path: /client

P.S.

I've created issue on github:

https://github.com/spring-guides/tut-spring-boot-oauth2/issues/80

and made the pull request:

https://github.com/spring-guides/tut-spring-boot-oauth2/pull/81

P.S.2

Finally my pull request was merged: https://github.com/spring-guides/tut-spring-boot-oauth2/pull/81

这篇关于由于cookie冲突(授权代码机制),官方Spring安全性oauth2示例不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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