new無语 转载请注明原创出处,谢谢!
前后端分离的方案大多基于JWT Token来进行实现的。个人还是比较喜欢OAuth2的认证方式,简单做下处理。实现OAuth2的前后分离认证。
个人大概思路是这个样子的。
实现思路
之前我实现的简单的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<ClientRegistration> clientRegistrations = null;
ResolvableType type = ResolvableType.forInstance(clientRegistrationRepository).as(Iterable.class);
if (type != ResolvableType.NONE && ClientRegistration.class.isAssignableFrom(type.resolveGenerics()[0])) {
clientRegistrations = (Iterable<ClientRegistration>) 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支持实现就不说了。都上传到码云上了。大家可以查看,有问题可以提出来,一同改进。
网友评论