oauth2 使用密码方式获取token
1,Maven主要的依赖,没有使用数据库相关依赖
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example.oauth</groupId>
<artifactId>password</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>password</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</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>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</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>
</project>
2,编写配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
// accessToken 过期
private int accessTokenValiditySecond = 60 * 60 * 2; //2小时
private int refreshTokenValiditySecond = 60 * 60 * 24 * 7; // 7 天
public void configure(ClientDetailsServiceConfigurer configurer) throws Exception {
// 使用过内存的方式配置客户端信息
configurer.inMemory()
.withClient("yyy_client")
.secret(passwordEncoder()
.encode("yyy_secret")) //
.authorizedGrantTypes("password","client_credentials","refresh_token")
.scopes("all") //设置权限类型,用密码,客户端,刷新的token 权限为所有人
.accessTokenValiditySeconds(accessTokenValiditySecond)
.refreshTokenValiditySeconds(refreshTokenValiditySecond);
}
//定义授权和令牌端点和令牌服务
public void configure(AuthorizationServerEndpointsConfigurer endpointsConfigurer){
//刷新令牌时需要的认证管理和用户信息来源
endpointsConfigurer.authenticationManager(authenticationManager()).allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST);
endpointsConfigurer.authenticationManager(authenticationManager());
endpointsConfigurer.userDetailsService(userDetailsService());
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
// 允许表单认证,这一行必须配置,采用post表单提交用到
oauthServer.allowFormAuthenticationForClients();
//允许 check_token 访问
oauthServer.checkTokenAccess("permitAll()");
}
@Bean
AuthenticationManager authenticationManager() {
AuthenticationManager authenticationManager = new AuthenticationManager() {
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
return daoAuhthenticationProvider().authenticate(authentication);
}
};
return authenticationManager;
}
@Bean
public AuthenticationProvider daoAuhthenticationProvider() {
DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
daoAuthenticationProvider.setUserDetailsService(userDetailsService());
daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
return daoAuthenticationProvider;
}
// 设置添加用户信息,正常应该从数据库中读取
@Bean
UserDetailsService userDetailsService() {
InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
userDetailsService.createUser(User.withUsername("user_1").password(passwordEncoder().encode("123456"))
.authorities("ROLE_USER").build());
userDetailsService.createUser(User.withUsername("user_2").password(passwordEncoder().encode("123456"))
.authorities("ROLE_USER").build());
return userDetailsService;
}
@Bean
PasswordEncoder passwordEncoder() {
// 加密方式
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
return passwordEncoder;
}
}
这里暂时使用内存中的数据,在后面使用数据库去连接进行处理
3,然后启动类:
@SpringBootApplication
public class SSOApplication {
public static void main(String[] args) {
SpringApplication.run(SSOApplication.class, args);
}
}
5.测试
程序运行后使用postman如下:
用python编写脚本测试
import requests
url = 'http://localhost:8080/oauth/token'
param={
'grant_type':'password',
'username':'admin',
'password':'admin',
'client_id':'client1',
'client_secret':'secret',
'scop':'all'
}
r = requests.post(url,data=param)
print(r.text)
输出结果:
{
"access_token":"c93089cf-3e38-4212-8f1d-4d3db275a97e",
"token_type":"bearer",
"expires_in":42642,
"scope":"all"
}