oauth2 授权码模式 流程说明和接口整理

4 篇文章 0 订阅
2 篇文章 0 订阅

一、说明

oauth2 授权模式一共有四种,即隐式授权模式、授权码授权模式、密码授权模式和客户端授权模式。
这里仅对授权码授权模式所包含的流程和接口做说明和整理。
具体的概念和源码解读,资料有很多,可以自行去搜索学习。

二、流程说明

假设有这样一个场景:现有A系统和B系统,A系统想要使用B系统的账号来做三方登录,那么A系统就必须要获取B系统的授权,以便拿到B系统的用户信息。(可以参考微信账号的三方登录场景)
想要实现以上场景就可以使用oauth2的授权码模式,具体流程参考下图:

oauth2-授权码授权模式

其中clientId、clientSecret、redirectUri等信息涉及到的表是:oauth_client_details

三、所涉及到的接口以及代码整理

以下会对接口做简要说明,最重要的是整理涉及到的自定义配置
想要了解具体代码逻辑实现,可以重点看一下 AuthorizationEndpoint 这个类的源码

① /oauth/authorize 接口 GET请求

该接口对应上图的第一步,即传递参数,获取B系统的登录界面。

authorize-get
oauth2的登录界面很丑,很难满足实际使用场景,可以通过在认证服务器配置中使用自定义的登录页面替换。

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .csrf().disable()
        .requestMatchers().antMatchers("/login*","/oauth/authorize").and()
        .authorizeRequests()
        .anyRequest().permitAll()
        .and()
        .formLogin()
         //使用自定义的登录页面
        .loginPage("/login.html")
        .loginProcessingUrl("/login");
}

注:如果同时存在认证服务器配置和资源服务牌配置的话,需要设置认证服务器配置的优先级高于资源服务器配置。

/**
 * 认证服务器配置
 */
@Configuration
@Order(1) //设置该配置的优先级
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
		...
		...
}


/**
 * 资源服务器配置
 */
@Configuration
@EnableResourceServer
public class UnifiedResourceServerConfig extends ResourceServerConfigurerAdapter {
		...
		...
}

② /oauth/confirm_access 接口

该接口会重定向到授权页面,同样,oauth2的授权界面很难满足实际使用场景,可以通过配置替换为自定义的授权页面。

//替换为自定义的授权页面
endpoints.pathMapping("/oauth/confirm_access", "/custom/confirm_access");
//自定义授权页面
@Controller
@SessionAttributes("authorizationRequest")
public class GrantController {
    @RequestMapping("/custom/confirm_access")
    public ModelAndView getAccessConfirmation(Map<String, Object> model, HttpServletRequest request) {
        AuthorizationRequest authorizationRequest = (AuthorizationRequest) model.get("authorizationRequest");
        ModelAndView view = new ModelAndView();
        view.setViewName("grant");
        view.addObject("clientId", authorizationRequest.getClientId());
        view.addObject("scopes",authorizationRequest.getScope());
        return view;
    }
}
<!-- 自定义授权页面 -->
<form method="post" action="/oauth/authorize">
    <input type="hidden" name="user_oauth_approval" value="true">
    <div th:each="item:${scopes}">
        <input type="radio" th:name="'scope.'+${item}" value="true" hidden="hidden" checked="checked"/>
    </div>
    <button class="btn" type="submit"> 同意/授权</button>
</form>

授权后的信息存放在 oauth_approvals 表中。
具体源码可以查看 JdbcApprovalStore 类,该类中的sql默认是使用 Mysql 语法,同样可以通过自定义替换成别的数据库语法。

③ /oauth/authorize 接口 POST请求

该接口会生成code码,最终会重定向到A系统的redirectUrl地址,并将生成的code码以参数的形式传递到A系统。

生成的code码保存在 oauth_code 表中。
具体源码可以查看 JdbcAuthorizationCodeServices 类。

可以在代码中自定义code码生成规则

public class UnifiedAuthorizationCodeServices extends JdbcAuthorizationCodeServices {
    public UnifiedAuthorizationCodeServices(DataSource dataSource) {
        super(dataSource);
    }

    private RandomValueStringGenerator generator = new RandomValueStringGenerator(13);

    @Override
    public String createAuthorizationCode(OAuth2Authentication authentication) {
        String code = generator.generate();
        store(code, authentication);
        return code;
    }
}

配置代码

@Bean
public AuthorizationCodeServices authorizationCodeServices() {
    return new UnifiedAuthorizationCodeServices(dataSource);
}

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    // token 携带额外信息
    TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
    tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer()));
    endpoints
            .userDetailsService(userDetailsService)
            .tokenStore(tokenStore())
            .tokenServices(defaultAuthorizationServerTokenServices())
            .authenticationManager(authenticationManager)
            .accessTokenConverter(getAccessTokenConverter())
            .exceptionTranslator(oauth2ResponseExceptionTranslator)
             //自定义sql查询语句
            .approvalStore(jdbcApprovalStore())
             //自定义授权码生成规则
            .authorizationCodeServices(authorizationCodeServices());

	//替换为自定义的授权页面
    endpoints.pathMapping("/oauth/confirm_access", "/custom/confirm_access");
}

④ /oauth/token 接口 authorization_code模式

该接口对应图中,A系统访问B系统,传递clientId,clientSecret,code,redirectUri等参数换取B系统的accessToken和refreshToken。

使用code换取token
有了B系统token,就可以通过token调用B系统的接口获取B系统的用户信息了。

  • 20
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值