目錄
一、oauth2
OAuth: OAuth(開放授權)是一個開放標準,允許用戶授權第三方網站訪問他們存儲在另外的服務提供者上的信息,而不需要將用戶名和密碼提供給第三方網站或分享他們數據的所有內容。
QQ登錄OAuth2.0:對於用戶相關的OpenAPI(例如獲取用戶信息,動態同步,照片,日誌,分享等),爲了保護用戶數據的安全和隱私,第三方網站訪問用戶數據前都需要顯式的向用戶徵求授權。
QQ登錄OAuth2.0採用OAuth2.0標準協議來進行用戶身份驗證和獲取用戶授權,相對於之前的OAuth1.0協議,其認證流程更簡單和安全。
地址:https://wiki.connect.qq.com
二、OAuth認證和授權的過程
OAuth認證和授權的過程如下:
1、用戶訪問第三方網站網站,想對用戶存放在服務商的某些資源進行操作。
2、第三方網站向服務商請求一個臨時令牌。
3、服務商驗證第三方網站的身份後,授予一個臨時令牌。
4、第三方網站獲得臨時令牌後,將用戶導向至服務商的授權頁面請求用戶授權,然後這個過程中將臨時令牌和第三方網站的返回地址發送給服務商。
5、用戶在服務商的授權頁面上輸入自己的用戶名和密碼,授權第三方網站訪問所相應的資源。
6、授權成功後,服務商將用戶導向第三方網站的返回地址。
7、第三方網站根據臨時令牌從服務商那裏獲取訪問令牌。
8、服務商根據令牌和用戶的授權情況授予第三方網站訪問令牌。
9、第三方網站使用獲取到的訪問令牌訪問存放在服務商的對應的用戶資源。
流程總結:
1、 生成授權鏈接,獲取授權碼
2、 使用授權碼獲取AccessToken
3、 使用AccessToken獲取openId
4、 使用openId獲取用戶信息
三、OAuth2爲我們提供了四種授權方式
1、授權碼模式(authorization code)用在客戶端與服務端應用之間授權
2、簡化模式(implicit)用在移動app或者web app(這些app是在用戶的設備上的,如
在手機上調起微信來進行認證授權)
3、密碼模式(resource owner password credentials)應用直接都是受信任的(都是由一家公司開發的)
4、客戶端模式(client credentials)用在應用API訪問
四、OAuth2環境搭建OAuth2環境搭建
oauth2-server:OAUTH2認證授權中心服務
order_service: 普通微服務,驗證授權服務
1、認證授權中心服務
1)、密碼模式
Maven依賴
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
</parent>
<!-- 管理依賴 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.M7</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- 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.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
</dependencies>
<!-- 注意: 這裏必須要添加, 否者各種依賴有問題 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/libs-milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
創建配置信息
// 配置授權中心信息
@Configuration
@EnableAuthorizationServer // 開啓認證授權中心
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
// accessToken有效期
private int accessTokenValiditySeconds = 7200; // 兩小時
// 添加商戶信息
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// withClient appid
clients.inMemory().withClient("client_1").secret(passwordEncoder().encode("123456"))
.authorizedGrantTypes("password","client_credentials","refresh_token").scopes("all").accessTokenValiditySeconds(accessTokenValiditySeconds);
}
// 設置token類型
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager()).allowedTokenEndpointRequestMethods(HttpMethod.GET,
HttpMethod.POST);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
// 允許表單認證
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("1234567"))
.authorities("ROLE_USER").build());
return userDetailsService;
}
@Bean
PasswordEncoder passwordEncoder() {
// 加密方式
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
return passwordEncoder;
}
}
啓動授權服務
@SpringBootApplication
public class AppOauth2 {
public static void main(String[] args) {
SpringApplication.run(AppOauth2.class, args);
}
}
驗證授權
獲取accessToken請求地址: http://localhost:8080/oauth/token
參數
grant_type、username、password、client_id、client_secret、scope
驗證accessToken是否有效
http://localhost:8080/oauth/check_token?token=b212eaec-63a7-489d-b5a2-883ec248c417
刷新新的accessToken
需要配置
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.authenticationManager(authenticationManager()).allowedTokenEndpointRequestMethods(HttpMethod.GET,
HttpMethod.POST);
endpoints.authenticationManager(authenticationManager());
endpoints.userDetailsService(userDetailsService());
}
2)、授權模式(常用)
新增授權權限
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// withClient appid
clients.inMemory().withClient("client_1").secret(passwordEncoder().encode("123456"))
.authorizedGrantTypes("password", "client_credentials", "refresh_token", "authorization_code")
.scopes("all").redirectUris("http://www.mayikt.com")
.accessTokenValiditySeconds(accessTokenValiditySeconds)
.refreshTokenValiditySeconds(refreshTokenValiditySeconds);
}
訪問報錯
User must be authenticated with Spring Security before authorization can be completed.
解決辦法 添加Security權限
@Component
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// 授權中心管理器
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
AuthenticationManager manager = super.authenticationManagerBean();
return manager;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
// 攔截所有請求,使用httpBasic方式登陸
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().httpBasic();
}
}