第一種: 簡單的 推薦 springboot 2++
只需要三個文件 application.yml controller POM
1) application.yml
okta:
oauth2:
issuer: https://dev-482025.oktapreview.com/oauth2/default
client-id: 0oaidl07zh1iY9KeM0h7
client-secret: QkVS1UIZCZab59_f4tavzDuzfb9Ead6jNxezMuR7
2) POM 依賴
<dependency>
<groupId>com.okta.spring</groupId>
<artifactId>okta-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.okta.spring/okta-spring-sdk -->
<dependency>
<groupId>com.okta.spring</groupId>
<artifactId>okta-spring-sdk</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
3) 測試controller
@RestController
public class HelloController {
@RequestMapping("/okta/test")
String home() {
return "home";
}
@GetMapping("/")
public String getMessageOfTheDay(Principal principal) {
return principal.getName() + ", this message of the day is boring";
}
}
4) 啓動類當然不能少
@SpringBootApplication
public class OktaDemo2Application {
public static void main(String[] args) {
SpringApplication.run(OktaDemo2Application.class, args);
}
@Configuration
static class OktaOAuth2WebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().anyRequest().authenticated()
.and().oauth2Client().and()
.oauth2Login()/*.and()
.oauth2ResourceServer().jwt()*/;
}
}
}
第二種:
package com.example.oktademo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.oidc.IdTokenClaimNames;
@Configuration
public class OAuth2LoginConfig {
@EnableWebSecurity
public static class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login();
}
}
}
上面是配置文件,下面是 application.yml 文件
server:
port: 8080
logging:
level:
root: INFO
org.springframework.web: INFO
org.springframework.security: INFO
# org.springframework.boot.autoconfigure: DEBUG
spring:
thymeleaf:
cache: false
security:
oauth2:
client:
registration:
okta:
client-id: 0oaie481w6oiaN8Tk0h7
client-secret: 9sDR2NO4k0Rh-M23HfzQzKYmjn-NJ9vkoJwadvhC
client-name: Okta Login Test
provider:
okta:
authorization-uri: https://dev-482025.oktapreview.com/oauth2/v1/authorize
token-uri: https://dev-482025.oktapreview.com/oauth2/v1/token
user-info-uri: https://dev-482025.oktapreview.com/oauth2/v1/userinfo
jwk-set-uri: https://dev-482025.oktapreview.com/oauth2/v1/keys
第三: 這個是controller 文件
package com.example.oktademo.controller;
import java.util.Collections;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.security.oauth2.core.OAuth2AccessToken;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Controller
public class OAuth2Controller {
@Autowired
private OAuth2AuthorizedClientService authorizedClientService;
@RequestMapping("/")
public String index(Model model, OAuth2AuthenticationToken authentication) {
OAuth2AuthorizedClient authorizedClient = this.getAuthorizedClient(authentication);
model.addAttribute("userName", authentication.getName());
model.addAttribute("clientName", authorizedClient.getClientRegistration().getClientName());
return "index";
}
private OAuth2AuthorizedClient getAuthorizedClient(OAuth2AuthenticationToken authentication) {
return this.authorizedClientService.loadAuthorizedClient(
authentication.getAuthorizedClientRegistrationId(), authentication.getName());
}
@RequestMapping("/userinfo")
public String userinfo(Model model,OAuth2AuthenticationToken authentication) {
// authentication.getAuthorizedClientRegistrationId() returns the
// registrationId of the Client that was authorized during the Login flow
OAuth2AuthorizedClient authorizedClient =
this.authorizedClientService.loadAuthorizedClient(
authentication.getAuthorizedClientRegistrationId(),authentication.getName());
OAuth2AccessToken accessToken = authorizedClient.getAccessToken();
System.out.println(accessToken.getTokenValue());
Map userAttributes = Collections.emptyMap();
String userInfoEndpointUri = authorizedClient.getClientRegistration()
.getProviderDetails().getUserInfoEndpoint().getUri();
if (!StringUtils.isEmpty(userInfoEndpointUri)) {// userInfoEndpointUri is optional for OIDC Clients
userAttributes = WebClient.builder()
.filter(oauth2Credentials(authorizedClient))
.build().get().uri(userInfoEndpointUri).retrieve().bodyToMono(Map.class).block();
}
model.addAttribute("userAttributes", userAttributes);
return "userinfo";
}
private ExchangeFilterFunction oauth2Credentials(OAuth2AuthorizedClient authorizedClient) {
return ExchangeFilterFunction.ofRequestProcessor(
clientRequest -> {
ClientRequest authorizedRequest = ClientRequest.from(clientRequest)
.header(HttpHeaders.AUTHORIZATION, "Bearer " +
authorizedClient.getAccessToken().getTokenValue()).build();
return Mono.just(authorizedRequest);
});
}
}
第四: POM文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>okta-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>okta-demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
</parent>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
<version>2.1.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.security.oauth.boot/spring-security-oauth2-autoconfigure -->
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.0.1.RELEASE</version>
</dependency>
<!-- <dependency> <groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId> </dependency> -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<dependency>
<groupId>com.okta.spring</groupId>
<artifactId>okta-spring-boot-starter</artifactId>
<version>0.6.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
第五: resources 源文件下面新建一個templates文件夾放入index.html 和userinfo.html
1) index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
<title>Spring Security - OAuth2 Login</title>
<meta charset="utf-8" />
</head>
<body>
<div style="float: right" th:fragment="logout" sec:authorize="isAuthenticated()">
<div style="float:left">
<span style="font-weight:bold">User: </span><span sec:authentication="name"></span>
</div>
<div style="float:none"> </div>
<div style="float:right">
<form action="#" th:action="@{/logout}" method="post">
<input type="submit" value="Logout" />
</form>
</div>
</div>
<h1>OAuth2 Login with Spring Security</h1>
<div>
You are successfully logged in <span style="font-weight:bold" th:text="${userName}"></span>
via the OAuth2 Client <span style="font-weight:bold" th:text="${clientName}"></span>
</div>
<div> </div>
<div>
<a href="/userinfo" th:href="@{/userinfo}">Display User Information</a>
</div>
</body>
</html>
2) userinfo.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
<title>Spring Security - OAuth2 User Information</title>
<meta charset="utf-8" />
</head>
<body>
<div th:substituteby="index::logout"></div>
<h1>OAuth2 User Information</h1>
<div>
<span style="font-weight:bold">User Attributes:</span>
<ul>
<li th:each="userAttribute : ${userAttributes}">
<span style="font-weight:bold" th:text="${userAttribute.key}"></span>:
<span th:text="${userAttribute.value}"></span>
</li>
</ul>
</div>
</body>
</html>
參考文章:
saml : https://developer.okta.com/blog/2017/03/16/spring-boot-saml 或https://github.com/oktadeveloper/okta-spring-boot-saml-example
oauth2: https://developer.okta.com/blog/2017/03/21/spring-boot-oauth