(2) 配置 application.yml
spring:
security:
oauth2:
client:
provider:
keycloak:
issuer-uri: http://localhost:8080/auth/realms/heartsuit
registration:
keycloak:
client-id: springsecurity
client-secret: 6b532289-4c11-4e62-acc0-5c67e13e4736
clientName: Keycloak
scope:
-
openid
-
profile
-
email
server:
port: 8000
(3) 启动应用
为了看到登录成功后的效果,这里增加一个 Controller ;然后运行应用。
@GetMapping(value = “/”)
public String index(Principal principal) {
return "Welcome " + principal;
}
在浏览器键入: http://localhost:8000/login ,返回一个页面,其中包含了 Keycloak 登录链接:

点击 Keycloak 登录链接,会自动跳转至 我们创建的 Keycloak 服务认证页:

输入在 Heartsuit 域下创建的用户: auth ,会进入我们之前配置的Home页,显示用户信息。
Note: 如果我们直接在浏览器中输入 http://localhost:8000 则会自动跳转到
http://localhost:8080/auth/realms/heartsuit/protocol/openid-connect/auth?response_type=code&client_id=springsecurity&state=Gd5Xj0PyueFcDtoQ6zC6w2wSVc4XjAbAFn8q_uu0qes%3D&redirect_uri=http://localhost:8000/login/oauth2/code/keycloak 链接。
可通过链接退出: http://localhost:8000/logout
借助 SpringSecurity 对 OpenID 的支持,我们几乎不用写什么代码就实现了 Keycloak 登录集成。下面简单了解下登录成功后的 Registration , AccessToken 。
实验2:查看Keycloak在我们应用中的注册信息
为了方便调试或查看 registration ,这里新增一个接口端点:
@GetMapping(value = “/user/reg”)
public String registration() {
ClientRegistration keycloakRegistration = this.clientRegistrationRepository.findByRegistrationId(“keycloak”);
log.info(keycloakRegistration.toString());
return keycloakRegistration.toString();
}
访问之后会返回 registration 信息,其中包含了 clientId , clientSecret , authorizationGrantType , redirectUri , scopes 等。

实验3:查看获取到的AccessToken
@GetMapping(value = “/user/token”)
public OAuth2AccessToken accessToken(OAuth2AuthenticationToken authentication) {
OAuth2AuthorizedClient authorizedClient = this.authorizedClientService.loadAuthorizedClient(
authentication.getAuthorizedClientRegistrationId(), authentication.getName());
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
return accessToken;
}

显然,这里的 tokenValue 是一个 JWT 字符串,我们到 https://jwt.io 解析一下:

实验4:通过AccessToken请求Keycloak的用户信息接口
定义抽象 API 绑定类,通过拦截器将获取到的 AccessToken 设置到后续请求头中,通过 RestTemplate 实现对 API 的请求:
public abstract class ApiBinding {
protected RestTemplate restTemplate;
public ApiBinding(String accessToken) {
this.restTemplate = new RestTemplate();
if (accessToken != null) {
this.restTemplate.getInterceptors().add(getBearerTokenInterceptor(accessToken));
} else {
this.restTemplate.getInterceptors().add(getNoTokenInterceptor());
}
}
private ClientHttpRequestInterceptor getBearerTokenInterceptor(String accessToken) {
return new ClientHttpRequestInterceptor() {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] bytes, ClientHttpRequestExecution execution) throws IOException {
request.getHeaders().add(“Authorization”, "Bearer " + accessToken);
return execution.execute(request, bytes);
}
};
}
private ClientHttpRequestInterceptor getNoTokenInterceptor() {
return new ClientHttpRequestInterceptor() {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] bytes, ClientHttpRequestExecution execution) throws IOException {
throw new IllegalStateException(“Can’t access the Keycloak API without an access token”);
}
};
}
}
将获取 AccessToken 的过程进行封装:
@Configuration
@Slf4j
public class SocialConfig {
@Bean
@RequestScope
public Keycloak keycloak(OAuth2AuthorizedClientService clientService) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String accessToken = null;
String userInfoEndpointUri = null;
if (authentication.getClass().isAssignableFrom(OAuth2AuthenticationToken.class)) {
OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;
String clientRegistrationId = oauthToken.getAuthorizedClientRegistrationId();
if (clientRegistrationId.equals(“keycloak”)) {
OAuth2AuthorizedClient client = clientService.loadAuthorizedClient(clientRegistrationId, oauthToken.getName());
if (client != null) {
accessToken = client.getAccessToken().getTokenValue();
userInfoEndpointUri = client.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri();
}
log.info(accessToken);
log.info(userInfoEndpointUri);
}
}
return new Keycloak(accessToken, userInfoEndpointUri);
}
}
public class Keycloak extends ApiBinding {
private String userInfoEndpointUri;
public Keycloak(String accessToken, String userInfoEndpointUri) {
super(accessToken);
this.userInfoEndpointUri = userInfoEndpointUri;
}
public String getProfile() {
return restTemplate.getForObject(userInfoEndpointUri, String.class);
}
}
在 Controller 中新增接口:通过 AccessToken 获取 keycloak 用户信息:
@GetMapping(value = “/user/info”)
public String info() {
String profile = keycloak.getProfile();
log.info(keycloak.getProfile());
return profile;
}

Controller 的完整代码:
@RestController
@Slf4j
public class HelloController {
@Autowired
private ClientRegistrationRepository clientRegistrationRepository;
@Autowired
private OAuth2AuthorizedClientService authorizedClientService;
@Autowired
Keycloak keycloak;
@GetMapping(value = “/”)
public String index(Principal principal) {
return "Welcome " + principal;
}
@GetMapping(value = “/user/reg”)
public String registration() {
ClientRegistration keycloakRegistration = this.clientRegistrationRepository.findByRegistrationId(“keycloak”);
log.info(keycloakRegistration.toString());
return keycloakRegistration.toString();
}
@GetMapping(value = “/user/token”)
public OAuth2AccessToken accessToken(OAuth2AuthenticationToken authentication) {
OAuth2AuthorizedClient authorizedClient = this.authorizedClientService.loadAuthorizedClient(
authentication.getAuthorizedClientRegistrationId(), authentication.getName());
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
return accessToken;
}
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。


既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Java)

最后
2020年在匆匆忙忙慌慌乱乱中就这么度过了,我们迎来了新一年,互联网的发展如此之快,技术日新月异,更新迭代成为了这个时代的代名词,坚持下来的技术体系会越来越健壮,JVM作为如今是跳槽大厂必备的技能,如果你还没掌握,更别提之后更新的新技术了。

更多JVM面试整理:

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
视频,并且会持续更新!**
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Java)
[外链图片转存中…(img-zbtvMJ42-1713788146797)]
最后
2020年在匆匆忙忙慌慌乱乱中就这么度过了,我们迎来了新一年,互联网的发展如此之快,技术日新月异,更新迭代成为了这个时代的代名词,坚持下来的技术体系会越来越健壮,JVM作为如今是跳槽大厂必备的技能,如果你还没掌握,更别提之后更新的新技术了。
[外链图片转存中…(img-mVCKd8uV-1713788146797)]
更多JVM面试整理:
[外链图片转存中…(img-tfr7ksrT-1713788146797)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
888

被折叠的 条评论
为什么被折叠?



