Oauth2.0搭建开放平台接口
?
開放平臺
類似qq互聯(lián)、微信開放平臺和螞蟻金服開放平臺等,可以實(shí)現(xiàn)qq聯(lián)合登陸、微信掃碼登陸等。在大型公司中,公司旗下的分公司等相互通訊也可以采用開放平臺形式對接口進(jìn)行授權(quán)使用。
?
?
Oauth
一個開放標(biāo)準(zhǔn),允許用戶授權(quán)第三方網(wǎng)站訪問他們存儲在另外的服務(wù)提供者上的信息,而不需要將用戶名和密碼提供給第三方網(wǎng)站或分析他們數(shù)據(jù)的所有內(nèi)容。
Oauth2.0相比1.0,其認(rèn)證流程更簡單和安全。
需要依賴springsecurity。
有四種授權(quán)模式
-
密碼模式(resource owner password credentials)
-
授權(quán)碼模式(authorization code)
-
簡化模式(implicit)
-
客戶端模式(client credentials)
其中密碼模式和授權(quán)碼模式最常用。
?
授權(quán)碼模式認(rèn)證和授權(quán)過程:
1.第三方網(wǎng)站向服務(wù)商請求一個臨時令牌。
2.服務(wù)商驗(yàn)證第三方網(wǎng)站的身份后,授予一個臨時令牌。
3.第三方網(wǎng)站獲取臨時令牌后,將用戶導(dǎo)向至服務(wù)商的授權(quán)頁面請求用戶授權(quán),然后這個過程中將臨時令牌和第三方網(wǎng)站的回調(diào)地址發(fā)送給服務(wù)商。
4.用戶在服務(wù)商的授權(quán)頁面上輸入自己的用戶名和密碼,授權(quán)第三方網(wǎng)站訪問所相應(yīng)的資源。
5.授權(quán)成功后,服務(wù)商會將用戶導(dǎo)向第三方網(wǎng)站的回調(diào)地址。
6.第三方網(wǎng)站根據(jù)臨時令牌從服務(wù)商獲取訪問令牌。
7.服務(wù)商根據(jù)令牌和用戶的授權(quán)情況授予第三方網(wǎng)站訪問令牌。
8.第三方網(wǎng)站使用獲取到的訪問令牌訪問存放在服務(wù)商的對應(yīng)的用戶資源。
?
?
諸如qq互聯(lián)和微信開放平臺等,獲取用戶相關(guān)信息的步驟通常如下:
1.生成授權(quán)鏈接,獲取授權(quán)碼code。
2.使用授權(quán)碼獲取accessToken。
3.使用accessToken獲取openid。
4.使用openid獲取用戶信息。
?
?
?
實(shí)踐
?
創(chuàng)建Oauth數(shù)據(jù)庫表,以下是我備份數(shù)據(jù)庫的sql語句
-- ---------------------------- -- Table structure for clientdetails -- ---------------------------- CREATE TABLE `clientdetails` (`appId` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NOT NULL,`resourceIds` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`appSecret` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`scope` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`grantTypes` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`redirectUrl` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`authorities` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`access_token_validity` int(11) NULL DEFAULT NULL,`refresh_token_validity` int(11) NULL DEFAULT NULL,`additionalInformation` varchar(4096) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`autoApproveScopes` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,PRIMARY KEY (`appId`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_zh_0900_as_cs ROW_FORMAT = Dynamic;-- ---------------------------- -- Table structure for oauth_access_token -- ---------------------------- CREATE TABLE `oauth_access_token` (`token_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`token` blob NULL,`authentication_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NOT NULL,`user_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`client_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`authentication` blob NULL,`refresh_token` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,PRIMARY KEY (`authentication_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_zh_0900_as_cs ROW_FORMAT = Dynamic;-- ---------------------------- -- Table structure for oauth_approvals -- ---------------------------- CREATE TABLE `oauth_approvals` (`userId` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`clientId` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`scope` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`status` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`expiresAt` timestamp(0) NULL DEFAULT NULL,`lastModifiedAt` timestamp(0) NULL DEFAULT NULL ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_zh_0900_as_cs ROW_FORMAT = Dynamic;-- ---------------------------- -- Table structure for oauth_client_details -- ---------------------------- CREATE TABLE `oauth_client_details` (`client_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NOT NULL,`resource_ids` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`client_secret` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`scope` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`authorized_grant_types` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`web_server_redirect_uri` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`authorities` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`access_token_validity` int(11) NULL DEFAULT NULL,`refresh_token_validity` int(11) NULL DEFAULT NULL,`additional_information` varchar(4096) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`autoapprove` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,PRIMARY KEY (`client_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_zh_0900_as_cs ROW_FORMAT = Dynamic;-- ---------------------------- -- Table structure for oauth_client_token -- ---------------------------- CREATE TABLE `oauth_client_token` (`token_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`token` blob NULL,`authentication_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NOT NULL,`user_name` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`client_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,PRIMARY KEY (`authentication_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_zh_0900_as_cs ROW_FORMAT = Dynamic;-- ---------------------------- -- Table structure for oauth_code -- ---------------------------- CREATE TABLE `oauth_code` (`code` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`authentication` blob NULL ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_zh_0900_as_cs ROW_FORMAT = Dynamic;-- ---------------------------- -- Table structure for oauth_refresh_token -- ---------------------------- CREATE TABLE `oauth_refresh_token` (`token_id` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_zh_0900_as_cs NULL DEFAULT NULL,`token` blob NULL,`authentication` blob NULL ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_zh_0900_as_cs ROW_FORMAT = Dynamic;?
?
創(chuàng)建授權(quán)中心項(xiàng)目。
pom.xml
<?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.1.8.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>oauthtest</artifactId><version>0.0.1-SNAPSHOT</version><name>oauthtest</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</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><!-- SpringBoot整合Web組件 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!-- springboot整合freemarker --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><!-->spring-boot 整合security --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!-- spring-cloud-starter-oauth2 --><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-jdbc</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>?
?
application.yml
spring:datasource:hikari:connection-test-query: SELECT 1minimum-idle: 1maximum-pool-size: 5pool-name: dbcp1driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/oauth?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456?
?
創(chuàng)建security配置文件
package com.example.oauthtest;import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;/*** security配置文件*/ @Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {//配置攔截請求為所有請求,授權(quán)模式為httpBasichttp.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().httpBasic();} }?
?
創(chuàng)建授權(quán)中心配置文件
package com.example.oauthtest;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; 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.oauth2.provider.token.TokenStore; import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore; import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; import org.springframework.security.provisioning.InMemoryUserDetailsManager;import javax.sql.DataSource;/*** 授權(quán)中心配置文件*/ @Configuration @EnableAuthorizationServer //開啟認(rèn)證授權(quán)中心 public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {@Autowiredprivate DataSource dataSource;@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()").allowFormAuthenticationForClients(); //允許表單登陸}@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {//添加授權(quán)用戶,類似在qq互聯(lián)創(chuàng)建一個賬號,然后會被分配一個client_id和secret//一般會用專門的項(xiàng)目或接口用來給用戶創(chuàng)建賬號,這里為了方便,直接添加測試賬號clients.jdbc(dataSource) //設(shè)置數(shù)據(jù)源.withClient("client1") //設(shè)置client_id.secret(new BCryptPasswordEncoder().encode("123456")) //設(shè)置client_secret.authorizedGrantTypes("password", "refresh_token", "authorization_code") //允許授權(quán)范圍.redirectUris("http://www.baidu.com") //回調(diào)地址.authorities("ROLE_ADMIN") //客戶端可以使用的權(quán)限.scopes("all") //范圍 暫不知道用處.accessTokenValiditySeconds(7200) //token過期時間.refreshTokenValiditySeconds(7200); //刷新token的有效時間}@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager()).userDetailsService(userDetailService());//不設(shè)置userDetailService的話刷新token會報錯}@Beanpublic AuthenticationManager authenticationManager() {AuthenticationManager authenticationManager = new AuthenticationManager() {@Overridepublic Authentication authenticate(Authentication authentication) throws AuthenticationException {return daoAuthenticationProvider().authenticate(authentication);}};return authenticationManager;}@Beanpublic AuthenticationProvider daoAuthenticationProvider() {DaoAuthenticationProvider provider = new DaoAuthenticationProvider();provider.setUserDetailsService(userDetailService());provider.setHideUserNotFoundExceptions(false);provider.setPasswordEncoder(passwordEncoder());return provider;}@Beanpublic PasswordEncoder passwordEncoder() {//加密方式return new BCryptPasswordEncoder();}@Beanpublic UserDetailsService userDetailService() {//創(chuàng)建security用戶InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager();userDetailsManager.createUser(User.withUsername("user1").password(new BCryptPasswordEncoder().encode("123456")).authorities("ROLE_USER").build());return userDetailsManager;}@Beanpublic TokenStore tokenStore() {//return new InMemoryTokenStore(); 使用內(nèi)存中的token storereturn new JdbcTokenStore(dataSource); //使用Jdbctoken store,即將token存進(jìn)數(shù)據(jù)庫} }?
?
springboot入口類
package com.example.oauthtest;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication public class OauthtestApplication {public static void main(String[] args) {SpringApplication.run(OauthtestApplication.class, args);}}?
?
啟動springboot入口類
用postman訪問接口
?
在token過期前10分鐘左右需要進(jìn)行刷新token,否則授權(quán)就失效了。
一般refreshToken的過期時間需要設(shè)置長一點(diǎn),否則refreshToken過期了就不能用來刷新了~
以上是密碼模式。
?
?
接下來使用授權(quán)碼模式。
1.獲取授權(quán)碼
打開瀏覽器,輸入http://localhost:8080/oauth/authorize?response_type=code&client_id=client1&redirect_uri=http://www.baidu.com?
?
如果彈出登陸框的話,就用賬號user1,密碼123456登陸
?
如果出現(xiàn)以下頁面
就選擇Approve,然后點(diǎn)擊按鈕,意思是同意授權(quán)
?
然后網(wǎng)頁會跳轉(zhuǎn)到百度,因?yàn)榘俣仁俏覀冊O(shè)置的回調(diào)地址
可以發(fā)現(xiàn)地址中后邊帶著一個code參數(shù),這個就是我們獲取到的授權(quán)碼
?
?
2.獲取token
使用postman
?
?
可以發(fā)現(xiàn)用授權(quán)碼模式獲取到的token跟密碼模式獲取的token一樣,說明在兩種授權(quán)模式同時使用的情況下,獲取到的token是一樣的,并不會產(chǎn)生覆蓋或者不一致的情況。
授權(quán)模式刷新token的方式和密碼模式一樣。
?
?
?
?
?
創(chuàng)建資源項(xiàng)目
pom.xml
<?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.1.8.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>oauthresource</artifactId><version>0.0.1-SNAPSHOT</version><name>oauthresource</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</artifactId></dependency><!-- SpringBoot整合Web組件 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><!-- springboot整合freemarker --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId></dependency><!-->spring-boot 整合security --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></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></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>?
?
?
配置文件application.yml
server:port: 8081logging:level:org.springframework.security: DEBUG security:oauth2:resource:token-info-uri: http://localhost:8080/oauth/check_tokenprefer-token-info: trueclient:access-token-uri: http://localhost:8080/oauth/tokenuser-authorization-uri: http://localhost:8080/oauth/authorizeclient-id: client1client-secret: 123456?
?
創(chuàng)建配置文件
package com.example.oauthresource;import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;@Configuration @EnableResourceServer //開啟資源服務(wù) public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {@Overridepublic void configure(HttpSecurity http) throws Exception {//攔截請求,被攔截到的需要驗(yàn)證token,一般在網(wǎng)關(guān)里面做,開放接口和內(nèi)部接口一般要獨(dú)立出來,這樣就不會一起攔截到了。http.authorizeRequests().antMatchers("/resource/**").authenticated();} }?
?
?
創(chuàng)建controller
?
package com.example.oauthresource;import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController;@RestController @RequestMapping("/resource") public class ResourceController {@RequestMapping("/getResource")public String getResource(){return "訪問到了資源文件";} }?
?
?
springboot入口類
package com.example.oauthresource;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;@SpringBootApplication public class OauthresourceApplication {public static void main(String[] args) {SpringApplication.run(OauthresourceApplication.class, args);}}?
?
?
啟動springboot入口類
使用postman訪問接口http://127.0.0.1:8081/resource/getResource
發(fā)現(xiàn)報了一個沒有權(quán)限的錯誤
?
在請求頭加上token再次請求
發(fā)現(xiàn)成功訪問到了接口。
需要注意的是,token前邊需要加上字符串bearer,與token值之間帶一個空格。
?
?
?
以上項(xiàng)目很多需要靈活設(shè)置的東西都是寫死的,等有空研究一下再換成活的。
總結(jié)
以上是生活随笔為你收集整理的Oauth2.0搭建开放平台接口的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: fni matlab,使用Matlab求
- 下一篇: 职场达人必备!100本管理类的书籍