Spring Boot整合Spring Security简记-OAuth2 前后端分离+源码分析(十七)

new無语 转载请注明原创出处,谢谢!

Spring Security学习目录

前后端分离的方案大多基于JWT Token来进行实现的。个人还是比较喜欢OAuth2的认证方式,简单做下处理。实现OAuth2的前后分离认证。

个人大概思路是这个样子的。


Spring Boot整合Spring Security简记-OAuth2 前后端分离+源码分析(十七)_第1张图片
实现思路

之前我实现的简单的OAuth2的项目,是基于将请求存储在session中。

  • DefaultLoginPageGeneratingFilter:默认登陆页面过滤器。
  • OAuth2AuthorizationRequestRedirectFilter:根据提供请求重定向到第三方授权页过滤器。
  • OAuth2LoginAuthenticationFilter:OAuth2登陆过滤器。处理第三方服务器回调请求。
  • SavedRequestAwareAuthenticationSuccessHandler:进行授权成功后处理。授权成功后,重定向回之前访问的页面(获取RequestCache中存储的地址)。
  • RequestCache 初始化在 ExceptionTranslationFilter中,要修改request保存地址,要重新实现一个RequestCache
  • HttpSessionRequestCache:在session中记录未授权跳转登陆之前的页面(request)等信息。

首先,我重新实现/login请求,不是让它硬性跳转到登陆页面。
我们就要对登陆路径进行修改,让其提示JSON格式的返回信息。这样在认证失效或失败的情况下,就提供了分离式的返回信息,提示客户端该进行登陆认证操作。

http.
    .loginPage("/login/oauthLogin")

LoginController

    @GetMapping("oauthLogin")
    public Object oauthLogin() {
        Map result = new HashMap();
        result.put("code", 201);
        result.put("msg", "Log in failure");
        return result;
    }

还要提供客户端的认证client的数量与对应的地址信息。

    @GetMapping("oauth2Client")
    public Object oauth2Client(HttpServletRequest request) {
        Iterable clientRegistrations = null;
        ResolvableType type = ResolvableType.forInstance(clientRegistrationRepository).as(Iterable.class);
        if (type != ResolvableType.NONE && ClientRegistration.class.isAssignableFrom(type.resolveGenerics()[0])) {
            clientRegistrations = (Iterable) clientRegistrationRepository;
        }
        StringBuffer url = request.getRequestURL();
        String tempContextUrl = url.delete(url.length() - request.getRequestURI().length(), url.length()).toString();

        List data = new ArrayList();
        clientRegistrations.forEach(registration -> {
            Map client = new HashMap();
            client.put("clientName", registration.getClientName());
            client.put("clientUrl", tempContextUrl + OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI + "/" + registration.getRegistrationId());
            data.add(client);
        });

        Map result = new HashMap();
        result.put("code", 200);
        result.put("data", data);
        return result;
    }

返回信息为:

{
    "code": 200,
    "data": [
        {
            "clientName": "gitee_login",
            "clientUrl": "http://localhost:8080/oauth2/authorization/gitee"
        }
    ]
}

提供给客户端进行验证的client信息。

在我们每次oauth2认证后,都会跳转到认证之前的页面,这种无认证之前的访问页面的情况,一样是跳转到服务器端的地址,我们web页面布置在http://127.0.0.1:9528,在认证成功之后,却跳转到127.0.0.1:8080,也就是后端项目的部署地址,要修改这种情况,就要对SavedRequestAwareAuthenticationSuccessHandler进行重新实现,跳转客户端的预留地址。

public class CustomSavedRequestAwareAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException {
        getRedirectStrategy().sendRedirect(request, response, "http://127.0.0.1:9528/#/login?state=" + request.getParameter("state"));
    }
}

实现CustomSavedRequestAwareAuthenticationSuccessHandler之后,要把它添加到successHandler中。

http.oauth2Login()
                   .successHandler(new CustomSavedRequestAwareAuthenticationSuccessHandler())

这里把oauth2认证状态码state做为唯一标示。
这里回调地址可以自定义实现,这里只是做了一个简单的讲述。
这样就实现了,OAuth2认证后,跳转到web页面。
最后,把状态码state拼接到URL后面,供web项目进行认证操作,这里后端提供一个验证state是否认证成功的接口。

    @GetMapping("checkState")
    public Object checkState(String state) {
        Map result = new HashMap();
        //判断逻辑
        result.put("code", 200);
        result.put("msg", "验证成功");
        return result;
    }

这里web支持实现就不说了。都上传到码云上了。大家可以查看,有问题可以提出来,一同改进。

你可能感兴趣的:(Spring Boot整合Spring Security简记-OAuth2 前后端分离+源码分析(十七))