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

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

什麼是開放平臺

經過開放本身平臺產品服務的各類API接口,讓其餘第三方開發者在開發應用時根據需求直接調用,例如微信登陸、QQ登陸、微信支付、微博登陸、熱門等。
讓第三方應用經過開發平臺,使得自身海量數據資源獲得沉澱(變現)
目前國內主流的網站的的開放平臺,都是基於oauth2.0 協議進行作的開放平臺git

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

  • 微博開放平臺受權機制流程圖

oauth2.0 受權碼模式

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

引入相關依賴

<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,密碼已經打在控制檯本身查便可

  • 受權確認

  • 登陸成功帶着code回調到目標接口

  • 經過/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")
    }

獲取上下文中的受權信息,傳給前端session

/**
     * 確認受權頁面
     *
     * @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;
    }

最終效果

  • 把用戶頭像等信息展現出來就蠻好看了

總結

相關文章
相關標籤/搜索