Oauth2Sso-vue axios转发/oauth/authorize未设置cookies问题

问题背景

在做Oauth2Sso单点登录时,需要在client.szile.com域名下请求一个需要登录才能访问的接口/secure/data,会302到oauth.szile.com的/oauth/authorize接口上进行认证、/oauth/authorize接口又会302到/login接口到登录页,在登录页使用表单登录成功后再302到client.szile.com域名下。

问题的产生

   问题是如果接口请求都是浏览器地址栏发出的一切都OK,但是如果使用axios发出的请求就不行🙅‍♂️,why ??? 

在这里插入图片描述
在这里插入图片描述

问题的原因

反复的对比发现,使用axios发请求后,Response中没有设置Cookie。
Cookie的值是SessionId,Oauth2Sso就是根据session中记录了登录成功后需要跳转的信息「client_id、redirect_uri、response_type、scope、state」。因为axios的请求没有设置Cookie,所以登录成功后无法找到进行跳转的信息,所以使用axios不会成功。

👌OK,找到问题原因了 ,想办法解决吧,怎么才能让Response设置Cookis呢?

定位与解决

就想到了Filter。

【1】 Cookie如何存储的?

SessionRepositoryFilter 是管理Session存储的。
org.springframework.session.web.http.SessionRepositoryFilter.SessionRepositoryRequestWrapper#commitSession 是提交Session的方法。而commitSession方法中

private void commitSession() {
            SessionRepositoryFilter<S>.SessionRepositoryRequestWrapper.HttpSessionWrapper wrappedSession = this.getCurrentSession();
            // 只有wrappedSesson 不为空时才会保存Cookie
            if (wrappedSession == null) {
                if (this.isInvalidateClientSession()) {
                    SessionRepositoryFilter.this.httpSessionIdResolver.expireSession(this, this.response);
                }
            } else {
                S session = wrappedSession.getSession();
                this.clearRequestedSessionCache();
                SessionRepositoryFilter.this.sessionRepository.save(session);
                String sessionId = session.getId();
                if (!this.isRequestedSessionIdValid() || !sessionId.equals(this.getRequestedSessionId())) {
                    SessionRepositoryFilter.this.httpSessionIdResolver.setSessionId(this, this.response, sessionId);
                }
            }

        }

是设置sessionId的。这里的httpSessionIdResolver默认实现是CookieHttpSessionIdResolver。
org.springframework.session.web.http.CookieHttpSessionIdResolver#setSessionId

public void setSessionId(HttpServletRequest request, HttpServletResponse response, String sessionId) {
        if (!sessionId.equals(request.getAttribute(WRITTEN_SESSION_ID_ATTR))) {
            request.setAttribute(WRITTEN_SESSION_ID_ATTR, sessionId);
            // 设置Cookie
            this.cookieSerializer.writeCookieValue(new CookieValue(request, response, sessionId));
        }
    }
【2】Session如何产生的?

由【1】知道只有wrappedSesson 不为空时才会保存Session到Cookie中。那么Session是在何时产生的呢?条件是什么?
debug定位到
org.springframework.security.web.access.ExceptionTranslationFilter#handleSpringSecurityException -> org.springframework.security.web.access.ExceptionTranslationFilter#sendStartAuthentication -> this.requestCache.saveRequest(request, response);

protected void sendStartAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, AuthenticationException reason) throws ServletException, IOException {
        SecurityContextHolder.getContext().setAuthentication((Authentication)null);
        // 保存request。其中创建的Session
        this.requestCache.saveRequest(request, response);
        this.logger.debug("Calling Authentication entry point.");
        this.authenticationEntryPoint.commence(request, response, reason);
    }

org.springframework.security.web.savedrequest.HttpSessionRequestCache#saveRequest

public void saveRequest(HttpServletRequest request, HttpServletResponse response) {
		// 创建Session的条件
        if (this.requestMatcher.matches(request)) {
            DefaultSavedRequest savedRequest = new DefaultSavedRequest(request, this.portResolver);
            if (this.createSessionAllowed || request.getSession(false) != null) {
                // getSession() 方法中创建的Session
                request.getSession().setAttribute(this.sessionAttrName, savedRequest);
                this.logger.debug("DefaultSavedRequest added to Session: " + savedRequest);
            }
        } else {
            this.logger.debug("Request not saved as configured RequestMatcher did not match");
        }

    }

最终有org.springframework.session.web.http.SessionRepositoryFilter.SessionRepositoryRequestWrapper#getSession(boolean)创建。
而创建的条件是this.requestMatcher.matches(request)。
在这里插入图片描述
最终定位到关键点是 Request的headers.Accept中不能包含application/json。

解决

所以在axios请求是设置header

headers: { 'Accept': 'text/html,application/xhtml+xml,application/xml,text/plain,*/*' }

这样就可以创建Session,并且设置Cookie。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

超人@不会飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值