首頁>技術>

一、模式描述

授權服務

驗證第三方服務的身份,驗證郵箱使用者的身份,記錄和管理認證Token,為資源伺服器提供Token校驗。場景:第三方網站藉助使用者的郵箱登入,並訪問郵箱賬戶的基礎資訊,頭像、名稱等。

資源服務

第三方服務透過郵箱賬戶登入後需要獲取的一些資訊,即理解為資源,儲存郵箱賬戶的資料資源。

第三方服務

即藉助郵箱使用者的賬戶,快速登入第三個服務,免去繁雜的註冊流程,有助於快速積累新使用者。

互動流程

第三方服務給使用者開放快速郵箱登入功能,引導使用者調到郵箱認證服務,透過認證後返回身份令牌到第三方服務,第三方服務攜帶令牌訪問郵箱的資源服務,獲取一些基本的郵箱使用者資訊。

二、專案配置管理1、案例結構

核心依賴

<dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-web</artifactId></dependency><dependency>    <groupId>org.springframework.security.oauth</groupId>    <artifactId>spring-security-oauth2</artifactId>    <version>2.1.3.RELEASE</version></dependency><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-security</artifactId></dependency>

這裡有兩個核心元件依賴:OAuth2元件和Security元件。

模組劃分

auth-server:授權服務resource-server:資源伺服器third-server:第三個服務2、配置描述

【授權服務】

OAuth2配置

這裡的配置管理的是第三方的授權流程和發放給第三方的身份證明ClientID和密碼,實際的場景就是第三方藉助郵箱賬號登入,首先就是向郵箱管理方提供材料,獲取訪問郵箱服務的身份證明,然後才能對接開放服務,這種模式在第三方對接業務中很常見。

/** * 模擬第三方授權配置 */@EnableAuthorizationServer@Configurationpublic class AuthConfig extends AuthorizationServerConfigurerAdapter {    @Resource    ClientDetailsService clientDetailsService;    /**     * 資源伺服器校驗Token     */    @Override    public void configure(AuthorizationServerSecurityConfigurer security) {        security.checkTokenAccess("permitAll()").allowFormAuthenticationForClients();    }    /**     * 第三方客戶端請求配置,和資源服務訪問的配置,不設定預設都可以訪問,提供預設回撥地址     */    @Override    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {        clients.inMemory()                .withClient("third01")                .secret(new BCryptPasswordEncoder().encode("third01"))                .resourceIds("resource-01")                .authorizedGrantTypes("authorization_code","refresh_token")                .scopes("all")                .redirectUris("http://localhost:8082/notify.html");    }    /**     * 配置訪問端點     */    @Override    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {        endpoints.authorizationCodeServices(authorizationCodeServices()).tokenServices(tokenServices());    }    /**     * 記憶體管理     */    @Bean    AuthorizationCodeServices authorizationCodeServices() {        return new InMemoryAuthorizationCodeServices();    }    /**     * Token管理規則     */    @Bean    AuthorizationServerTokenServices tokenServices() {        DefaultTokenServices services = new DefaultTokenServices();        services.setClientDetailsService(clientDetailsService);        services.setSupportRefreshToken(true);        services.setTokenStore(tokenStore());        services.setAccessTokenValiditySeconds(3600);        services.setRefreshTokenValiditySeconds(3600*7);        return services;    }    @Bean    TokenStore tokenStore() {        return new InMemoryTokenStore();    }}

通常需要資料庫儲存第三方資訊,可以到第OAuth2開源專案中,獲取表結構放到本地資料庫中,然後這裡換成資料來源載入模式即可,簡單的流程管理都在原始碼裡寫了SQL語句,資料來源引入即可。

Security配置

/** * 模擬本地使用者配置 */@Configurationpublic class SecurityConfig extends WebSecurityConfigurerAdapter {    /**     * 密碼加密方式     */    @Bean    public PasswordEncoder passwordEncoder(){        return new BCryptPasswordEncoder();    }    /**     * 記憶體中虛擬使用者和角色     */    @Override    protected void configure(AuthenticationManagerBuilder auth) throws Exception {        auth.inMemoryAuthentication()                .withUser("user")                .password(new BCryptPasswordEncoder().encode("123456"))                .roles("user");    }    /**     * 表單登入     */    @Override    protected void configure(HttpSecurity http) throws Exception {        http.csrf().disable().formLogin();    }}

基於這裡的配置管理郵箱使用者的認證流程,例如使用郵箱賬號密碼登入驗證,判斷授權是否成立,這裡管理的是服務本地的郵箱賬號,基於資料來源儲存資料在下面案例中都有。

【資源服務】

主要功能有三塊,配置第三方攜帶的Token身份令牌校驗機制,即訪問授權服務校驗介面,這裡是OAuth2自定義好的介面;配置resourceId資源服務的編號,用來控制第三個服務能訪問的資源服務範圍,屬於大的許可權點控制;模擬校驗使用者的Role角色,較精細的控制權限。

/** * 資源服務管理配置 */@Configuration@EnableResourceServerpublic class ResourceServerConfig extends ResourceServerConfigurerAdapter {    /**     * Token令牌校驗     */    @Bean    RemoteTokenServices tokenServices() {        RemoteTokenServices services = new RemoteTokenServices();        services.setCheckTokenEndpointUrl("http://localhost:8080/oauth/check_token");        services.setClientId("third01");        services.setClientSecret("third01");        return services;    }    /**     * 服務資源ID配置     */    @Override    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {        resources.resourceId("resource-01").tokenServices(tokenServices());    }    /**     * 模擬使用者許可權規則     */    @Override    public void configure(HttpSecurity http) throws Exception {        http.authorizeRequests()                .antMatchers("/user/**").hasRole("user")                .anyRequest().authenticated();    }}

【第三方服務】

主要提供兩個流程的模擬:請求授權服務獲取身份令牌;攜帶身份令牌請求資源服務獲取資料。這裡則是授權碼回撥介面的處理方式。

@Controllerpublic class NotifyController {    private static final Logger LOG = LoggerFactory.getLogger(NotifyController.class);    @Resource    private RestTemplate restTemplate;    @GetMapping("/notify.html")    public String notify(String code, Model model) {        if (code != null) {            MultiValueMap<String, String> map = new LinkedMultiValueMap<>();            map.add("code", code);            map.add("client_id", "third01");            map.add("client_secret", "third01");            map.add("redirect_uri", "http://localhost:8082/notify.html");            map.add("grant_type", "authorization_code");            Map<String,String> resp = restTemplate.postForObject("http://localhost:8080/oauth/token", map, Map.class);            String accessToken = resp.get("access_token");            LOG.info("身份令牌:{}",accessToken);            HttpHeaders headers = new HttpHeaders();            headers.add("Authorization", "Bearer " + accessToken);            HttpEntity<Object> httpEntity = new HttpEntity<>(headers);            ResponseEntity<String> entity = restTemplate.exchange("http://localhost:8081/user/resource", HttpMethod.GET, httpEntity, String.class);            model.addAttribute("notifyMsg", entity.getBody());        }        return "notify";    }}
三、測試流程

透過上述測試流程,對比常見的第三方登入機制,理解OAuth2的授權碼模式。

13
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • JS陣列中 forEach() 和 map() 的區別