问题
使用 Spring security oauth2 client 实现授权码模式,可以不用手动拼接url请求code和token等信息,用户登录成功之后可以在SuccessHandler中获取当前用户的信息。如果还想获取用户信息以外的授权资源,必须要有AccessToken,要怎么获取呢?先看下如何获取用户信息
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
配置文件
spring:
security:
oauth2:
client:
provider:
github:
authorization-uri: https://github.com/login/oauth/authorize
token-uri: https://github.com/login/oauth/access_token
user-info-uri: https://api.github.com/user
user-name-attribute: id
registration:
demo:
client-id: xxxxx
client-secret: xxxxx
client-name: oauth2-demo
provider: github
scope: profile
redirect-uri: http://localhost:8080/oauth2/callback
client-authentication-method: basic
authorization-grant-type: authorization_code
http:
log-request-details: true
logging:
level:
root: info
web: debug
配置类
package com.example.demo.configurations;
import com.example.demo.handler.Oauth2AuthenticationSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private Oauth2AuthenticationSuccessHandler oauth2AuthenticationSuccessHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login()
.redirectionEndpoint()
.baseUri("/oauth2/callback")
.and()
.successHandler(oauth2AuthenticationSuccessHandler)
;
}
}
SuccessHandler
package com.example.demo.handler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Slf4j
@Component
public class Oauth2AuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Autowired
public Oauth2AuthenticationSuccessHandler() {
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) throws IOException {
OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal();
if (oAuth2User != null) {
log.info(oAuth2User.toString());
}
response.sendRedirect("/index.html");
}
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>OAuth2 Demo</title>
</head>
<body>
<p>已登录</p>
</body>
</html>
分析
关键代码 OAuth2User oAuth2User = (OAuth2User) authentication.getPrincipal();
,在 IDEA 中查找跟Authentication相关的类:OAuth2AuthenticationToken
,OAuth2AuthorizedClient
,然后百度,找到一个非常有用的spring security 官方文档:链接,得到解决方案:使用 @RegisteredOAuth2AuthorizedClien
注解,登录成功后访问 http://localhost:8080/token
即可看到 AccessToken
HelloController
package com.example.demo.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@Slf4j
public class HelloController {
@GetMapping("/token")
@ResponseBody
public String token(@RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient) {
return authorizedClient.getAccessToken().getTokenValue();
}
}