基於oauth 2.0 實現第三方開放平臺

冷冷gg發表於2019-04-10

本文單純從簡單的技術實現來講,不涉及開放平臺的多維度的運營理念。

什麼是開放平臺

通過開放自己平臺產品服務的各種API介面,讓其他第三方開發者在開發應用時根據需求直接呼叫,例如微信登入、QQ登入、微信支付、微博登入、熱門等。
讓第三方應用通過開發平臺,使得自身海量資料資源得到沉澱(變現)
目前國內主流的網站的的開放平臺,都是基於oauth2.0 協議進行做的開放平臺

  • 微信開放平臺授權機制流程圖

基於oauth 2.0 實現第三方開放平臺

  • 微博開放平臺授權機制流程圖
    基於oauth 2.0 實現第三方開放平臺

oauth2.0 授權碼模式

授權碼模式(authorization code)是功能最完整、流程最嚴密的授權模式。 它的特點就是通過客戶端的後臺伺服器,與"服務提供商"的認證伺服器進行互動,能夠滿足絕大多數開放平臺認證授權的需求。

基於oauth 2.0 實現第三方開放平臺

引入相關依賴

<dependency>
         <groupId>org.springframework.cloud</groupId>
         <artifactId>spring-cloud-starter-oauth2</artifactId>
 </dependency>
 
<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-security</artifactId>
</dependency>
複製程式碼

配置認證伺服器

通過記憶體模式,初始化一個支援授權碼模式的客戶端

@Configuration
@AllArgsConstructor
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

	@Override
	@SneakyThrows
	public void configure(ClientDetailsServiceConfigurer clients) {
		clients.inMemory()
				.withClient("pigx") // client_id
				.secret("pigx") // client_secret
				.authorizedGrantTypes("authorization_code") // 該client允許的授權型別
				.scopes("app"); // 允許的授權範圍
	}
}
複製程式碼

初步完成,測試一下

注意這裡是 /oauth/authorize 不是 /oauth/token 介面,只需要帶 client_id 即可。

localhost:9999/oauth/authorize?client_id=pigx&response_type=code&redirect_uri=https://pig4cloud.com
複製程式碼
  • 先進行basic 登入,預設使用者user,密碼已經打在控制檯自己查即可
    基於oauth 2.0 實現第三方開放平臺
  • 授權確認
    基於oauth 2.0 實現第三方開放平臺
  • 登入成功帶著code回撥到目標介面
    基於oauth 2.0 實現第三方開放平臺
  • 通過/oauth/token獲取登入令牌

簡單的幾步就完成上圖微信或者其他網站的授權流程,不過目前為止 略顯簡陋

  1. 登入沒有介面,使用者密碼資料庫沒有儲存
  2. 確認授權介面太醜,沒有個性化

配置安全登入

  • 配置未登入攔截重定向到 loginPage
  • 配置登入完成提交的頁面路徑 這裡會被spring security 接管
@Primary
@Order(90)
@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
	@Override
	@SneakyThrows
	protected void configure(HttpSecurity http) {
		http
			.formLogin()
			.loginPage("/token/login")
			.loginProcessingUrl("/token/form")
			.and()
			.authorizeRequests()
			.anyRequest().authenticated();
	}
}
複製程式碼

認證伺服器配置使用者載入規則實現

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
	endpoints.userDetailsService(pigxUserDetailsService)
}

// 通過這步去載入資料的使用者名稱密碼
public interface UserDetailsService {
    UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;
}
複製程式碼

重寫原有認證頁面

預設邏輯/oauth/confirm_access,讓他重定向到我們自己的路徑,然後進行個性哈

@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
		endpoints
				.userDetailsService(pigxUserDetailsService)
				.pathMapping("/oauth/confirm_access", "/token/confirm_access")
	}
複製程式碼

獲取上下文中的授權資訊,傳給前端

	/**
	 * 確認授權頁面
	 *
	 * @param request
	 * @param session
	 * @param modelAndView
	 * @return
	 */
	@GetMapping("/confirm_access")
	public ModelAndView confirm(HttpServletRequest request, HttpSession session, ModelAndView modelAndView) {
		Map<String, Object> scopeList = (Map<String, Object>) request.getAttribute("scopes");
		modelAndView.addObject("scopeList", scopeList.keySet());

		Object auth = session.getAttribute("authorizationRequest");
		if (auth != null) {
			AuthorizationRequest authorizationRequest = (AuthorizationRequest) auth;
			ClientDetails clientDetails = clientDetailsService.loadClientByClientId(authorizationRequest.getClientId());
			modelAndView.addObject("app", clientDetails.getAdditionalInformation());
			modelAndView.addObject("user", SecurityUtils.getUser());
		}

		modelAndView.setViewName("ftl/confirm");
		return modelAndView;
	}

複製程式碼

最終效果

  • 把使用者頭像等資訊展示出來就蠻好看了
    基於oauth 2.0 實現第三方開放平臺

總結

相關文章