目录
4.获取code 客户端认证使用:client_secret_basic方式
一。准备环境
1.pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-authorization-server</artifactId>
<version>0.3.1</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
2.启动类
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
3.配置类authorization-server
我们按照官网来,并且修改一下回调地址:Getting Startedhttps://docs.spring.io/spring-authorization-server/docs/0.3.1/reference/html/getting-started.html
package cn.maicaii.demo.config;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
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.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.core.AuthorizationGrantType;
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
import org.springframework.security.oauth2.core.oidc.OidcScopes;
import org.springframework.security.oauth2.server.authorization.client.InMemoryRegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClient;
import org.springframework.security.oauth2.server.authorization.client.RegisteredClientRepository;
import org.springframework.security.oauth2.server.authorization.config.ClientSettings;
import org.springframework.security.oauth2.server.authorization.config.ProviderSettings;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.UUID;
/**
* auth2 认证服务器凭证
*
*
* @author zeng
* @version 2022.9.3
*/
@EnableWebSecurity
public class AuthorizationServerConfiguration extends OAuth2AuthorizationServerConfiguration {
/**
* 协议端点 安全过滤器链
* <p></p><a href="https://docs.spring.io/spring-authorization-server/docs/0.3.1/reference/html/protocol-endpoints.html">协议端点配置文档</a>
*/
@Bean
@Order(1)
public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)
throws Exception {
applyDefaultSecurity(http);
http
// 未通过身份验证时重定向到登录页面
// 授权端点
.exceptionHandling((exceptions) -> exceptions
.authenticationEntryPoint(
new LoginUrlAuthenticationEntryPoint("/login"))
);
return http.build();
}
/**
* 用于身份验证安全过滤器链
* <p><a href="https://docs.spring.io/spring-security/reference/servlet/authentication/index.html">用于身份验证安全过滤器链配置文档</a></p>
*/
@Bean
@Order(2)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http)
throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().authenticated()
)
//表单登录处理从
//授权服务器过滤器链
.formLogin(Customizer.withDefaults());
return http.build();
}
/**
* 用于进行查询身份,验证的用户的UserDetailsService实例。
* 详情查看spring-security的UserDetails
*
* @return
*/
@Bean
public UserDetailsService userDetailsService() {
UserDetails userDetails = User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(userDetails);
}
/**
* 用于管理和存储客户端 目前支持mysql和 内存
*
*
* @return
*/
@Bean
public RegisteredClientRepository registeredClientRepository() {
RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())
.clientId("messaging-client")
.clientSecret("{noop}secret")
.clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.authorizationGrantType(AuthorizationGrantType.REFRESH_TOKEN)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
// .redirectUri("http://127.0.0.1:8080/login/oauth2/code/messaging-client-oidc")
.redirectUri("https://www.baidu.com")
.scope(OidcScopes.OPENID)
.scope("message.read")
.scope("message.write")
.clientSettings(ClientSettings.builder().requireAuthorizationConsent(true).build())
.build();
return new InMemoryRegisteredClientRepository(registeredClient);
}
/**
* JWKSource 用于签名访问令牌。
*
* @return
* @see com.nimbusds.jose.jwk.source.JWKSource
*/
@Bean
public JWKSource<SecurityContext> jwkSource() {
KeyPair keyPair = generateRsaKey();
RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
RSAKey rsaKey = new RSAKey.Builder(publicKey)
.privateKey(privateKey)
.keyID(UUID.randomUUID().toString())
.build();
JWKSet jwkSet = new JWKSet(rsaKey);
return new ImmutableJWKSet<>(jwkSet);
}
/**
* 带有启动生成的密钥的密钥对,用于创建上面的 {@code com.nimbusds.jose.jwk.source.JWKSource }。
*
* @see java.security.KeyPair
*/
private static KeyPair generateRsaKey() {
KeyPair keyPair;
try {
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(2048);
keyPair = keyPairGenerator.generateKeyPair();
} catch (Exception ex) {
throw new IllegalStateException(ex);
}
return keyPair;
}
/**
* 用于配置授权服务器的授权端点
* @see ProviderSettings#builder()
*/
@Bean
public ProviderSettings providerSettings() {
return ProviderSettings.builder().build();
}
}
4.获取code 客户端认证使用:client_secret_basic方式
后面我会说其他几种认证方式,可以在我的博客文档查看,我们先跑通
第一步:用浏览器访问
http://localhost:8080/oauth2/authorize?response_type=code&client_id=messaging-client&&scope=openid%20message.read%20message.write&redirect_uri=https://www.baidu.com
第二步:然后浏览器会重定向到:我们输入配置的用户名:user,密码:password然后点击sigin in
第三步:授权
然后我们就得到code了
5.获取token
postman方式
用postman请求以下POST地址:
获取Cookie的方式:访问:http://localhost:8080/
配置认证方式:
也就是配置一个请求头:
Authorization:Basic Base64.encoder("clientId:clientSecret") // 方式
我们的测试程序:
Authorization:Basic bWVzc2FnaW5nLWNsaWVudDpzZWNyZXQ=
点击send获取token
结果
{
"access_token": "eyJraWQiOiJjNDhhNmE5OC04YWFiLTRkYjAtOGQ4My0xNDhmNmY0ZjFjMTgiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiYXVkIjoibWVzc2FnaW5nLWNsaWVudCIsIm5iZiI6MTY2MjE5OTE5OSwic2NvcGUiOlsib3BlbmlkIiwibWVzc2FnZS5yZWFkIiwibWVzc2FnZS53cml0ZSJdLCJpc3MiOiJodHRwOlwvXC9sb2NhbGhvc3Q6ODA4MCIsImV4cCI6MTY2MjE5OTQ5OSwiaWF0IjoxNjYyMTk5MTk5fQ.UFsaBNAomUavimJsSRb3OHLaZqFNXLHv6bGIqqrvDnQi-9wVTrRBGVLLY3hDDHUbEPftMt8kjb0ciCJPpk0og1zZB3alq_TWt90MbeDTk33O0qxKDn7GhrJg8jVAdWzSRN0O02t6u3lPGJnHbaRLWLGTrDPHoawXSdF_RdL0n61yLva2pbNAAzbtBAGOoYCRs96r9e2XfRfLlg8ax82SVHu5gRgxlnI_GZY61qY4lAKh4kxE3EBr6b8mY5lLsnbfc1XvrpKSyhxICaiT3uWcNaFetuFPCj06ozbp6gVWzpxS1HlL_zh6-CNrMVf0vYjRJK46MDHbRjKdU1ovG1olDw",
"refresh_token": "dguNujXa8wTgPFdpHPSrHXTTzEuJtMGHTKqnsdK2QQ8YlNUt1jX6SX6JspGqHS10TLXRCwWOusAklLDRT3soqijJjyt8zypSDuNhLABHEgJ26xM5IRHDa6uj8UulF_uw",
"scope": "openid message.read message.write",
"id_token": "eyJraWQiOiJjNDhhNmE5OC04YWFiLTRkYjAtOGQ4My0xNDhmNmY0ZjFjMTgiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2VyIiwiYXVkIjoibWVzc2FnaW5nLWNsaWVudCIsImF6cCI6Im1lc3NhZ2luZy1jbGllbnQiLCJpc3MiOiJodHRwOlwvXC9sb2NhbGhvc3Q6ODA4MCIsImV4cCI6MTY2MjIwMDk5OSwiaWF0IjoxNjYyMTk5MTk5fQ.SdN_R2POPN6A42CYXM86umTjFFmi4kv0wDkIdJAtWXCgKr4iVPoEO5AN9aJW909t62U3QbIPdvPXT-Is7dDhsDVjsV6BWfOrluXrOUN8VGi9p_84MUiKzk_So4U4tAuikQSPxOCnbD35WEzFjBYTaKE-up23xXZ_FEKsdEQRFmSGQgB6H53Dx3Mtw71op_GKbAkmQGjR1jbmnr7jRa9SlhquLpW4gsWfWjvWeXoP7xlwivwCrV590LvPKrZuFKPjEchDO4UZWCJK1H9j_rQgadcfhvvy2Enng_QEE7ZRmfY8RGeIyV4MrOP4aqQq3NChsvbsdF9AIvksN4732LytyA",
"token_type": "Bearer",
"expires_in": 300
}
6.说一下客户端认证:
-
client_secret_basic
-
client_secret_post
-
client_secret_jwt
-
private_key_jwt
-
none
(public clients)
其中 client_secret_jwt和private_key_jwt是auth2.1的新规范