OAuth2.0认证登录服务端实现详解

OAuth2.0认证登录服务端实现详解

OAuth2.0是目前互联网环境中广泛使用的认证授权框架,用于处理用户授权第三方应用程序访问其私有数据的过程。本篇博客将会介绍OAuth2.0的实现原理以及基于Java语言实现OAuth2.0认证登录服务端的详细步骤。

OAuth2.0实现原理

OAuth2.0的实现原理可以简单概括为以下四个步骤:

  1. 客户端(即第三方应用程序)向认证服务器发起认证请求。
  2. 认证服务器返回一个授权令牌(access token),用于客户端访问授权资源。
  3. 客户端使用授权令牌向资源服务器发起访问请求。
  4. 资源服务器验证授权令牌,验证通过后返回资源数据。

在OAuth2.0的实现中,常用的授权方式有四种:

  • 授权码模式(Code Grant):这是目前最常用的授权方式,客户端通过重定向用户授权页面,引导用户授权后获取一个授权码,再通过这个授权码获取access token。
  • 简化模式(Implicit Grant):这种方式简化了授权码模式中的获取access token的步骤,由浏览器直接获得access token。
  • 密码模式(Resource Owner Password Credentials Grant):该方式需要用户将自己的用户名和密码直接提交给客户端,客户端再通过这个用户名和密码直接向服务器请求access token。
  • 客户端凭证模式(Client Credentials Grant):该方式仅适用于客户端请求自己的资源的情况下,客户端使用自己的验证信息向服务器请求access token。

在本篇博客中,我们主要介绍前两种授权方式的实现。

OAuth2.0认证登录服务端实现

1. 授权码模式实现

1.1 配置文件

在Spring Boot的配置文件(application.properties)中增加以下配置:

# 配置客户端信息
spring.security.oauth2.client.registration.demo-client.client-id=your_client_id
spring.security.oauth2.client.registration.demo-client.client-secret=your_client_secret
spring.security.oauth2.client.registration.demo-client.redirect-uri=http://localhost:8080/login/oauth2/code/demo-client
spring.security.oauth2.client.registration.demo-client.scope=user_info
spring.security.oauth2.client.registration.demo-client.authorization-grant-type=authorization_code

# 配置认证服务器信息
spring.security.oauth2.client.provider.demo-server.token-uri=http://localhost:8081/oauth/token
spring.security.oauth2.client.provider.demo-server.authorization-uri=http://localhost:8081/oauth/authorize
spring.security.oauth2.client.provider.demo-server.user-info-uri=http://localhost:8081/userinfo
spring.security.oauth2.client.provider.demo-server.user-name-attribute=name

其中,your_client_idyour_client_secret需要替换为自己在认证服务器上注册的应用的client id和client secret。redirect-uri即为客户端在认证服务器上注册时填写的回调地址,scope为授权范围,例如"user_info"表示访问用户信息。authorization-grant-type选择authorization_code授权模式,token-uri为认证服务器颁发token的地址,authorization-uri为用于用户授权的页面地址,user-info-uri为获取用户信息的地址。

1.2 Controller代码实现

在Spring Boot项目中,我们可以使用@EnableOAuth2Client和@EnableOAuth2Sso注解来实现客户端的授权登录。在授权码模式下,需要增加一个授权码回调处理的Controller,如下所示:

@Controller
public class OAuth2LoginController {

    @GetMapping("/login")
    public String login() {
        return "login";
    }

    @GetMapping("/loginSuccess")
    public String loginSuccess() {
        return "loginSuccess";
    }
    
    @GetMapping("/login/oauth2/code/demo-client")
    public String loginByOAuth2Code(HttpServletRequest request) {
        return "redirect:/loginSuccess";
    }

}

其中,login为登录页面,loginSuccess为登录成功后显示的页面。loginByOAuth2Code方法为接收回调后的处理方法。

1.3 Security配置

OAuth2.0的实现需要在Security中配置。

@Configuration
@EnableWebSecurity
@EnableOAuth2Client
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private ClientRegistrationRepository clientRegistrationRepository;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/login**").permitAll().anyRequest().authenticated().and().oauth2Login();
    }

    @Override
    protected void configure(OAuth2ClientAuthenticationProcessingFilter filter) throws Exception {
        super.configure(filter);
        filter.setAuthenticationSuccessHandler(new OAuth2SuccessHandler());
        filter.setApplicationEventPublisher(applicationEventPublisher);
    }

    @Bean
    public WebClient webClient(ClientRegistrationRepository clientRegistrations) {
        ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 = new ServletOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, new DefaultOAuth2AuthorizedClientManager(clientRegistrations));
        oauth2.setDefaultClientRegistrationId("demo-client");
        return WebClient.builder().filter(oauth2).build();
    }

    @Bean
    public OAuth2AuthorizedClientRepository authorizedClientRepository() {
        return new HttpSessionOAuth2AuthorizedClientRepository();
    }

    @Bean
    public AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository() {
        return new HttpSessionOAuth2AuthorizationRequestRepository();
    }

}

其中,clientRegistrationRepository即为上面配置文件中的配置信息。

2. 简化模式实现

2.1 配置文件

与授权码模式不同,简化模式的配置文件(application.properties)中不需要配置redirect-uri和client-secret:

spring.security.oauth2.client.registration.demo-client.client-id=your_client_id
spring.security.oauth2.client.registration.demo-client.scope=user_info
spring.security.oauth2.client.registration.demo-client.authorization-grant-type=implicit

spring.security.oauth2.client.provider.demo-server.token-uri=http://localhost:8081/oauth/token
spring.security.oauth2.client.provider.demo-server.authorization-uri=http://localhost:8081/oauth/authorize
spring.security.oauth2.client.provider.demo-server.user-info-uri=http://localhost:8081/userinfo
spring.security.oauth2.client.provider.demo-server.user-name-attribute=name

2.2 Controller代码实现

在简化模式下,因为浏览器会直接获得access token,所以不需要接收任何回调,可以将登录成功后跳转的页面放到配置文件中:

spring.security.oauth2.client.registration.demo-client.client-id=your_client_id
spring.security.oauth2.client.registration.demo-client.scope=user_info
spring.security.oauth2.client.registration.demo-client.authorization-grant-type=implicit
spring.security.oauth2.client.registration.demo-client.redirect-uri=http://localhost:8080/loginSuccess

spring.security.oauth2.client.provider.demo-server.token-uri=http://localhost:8081/oauth/token
spring.security.oauth2.client.provider.demo-server.authorization-uri=http://localhost:8081/oauth/authorize
spring.security.oauth2.client.provider.demo-server.user-info-uri=http://localhost:8081/userinfo
spring.security.oauth2.client.provider.demo-server.user-name-attribute=name

/login为登录页面,/loginSuccess为登录成功后显示的页面。

2.3 Security配置

与授权码模式实现的Security配置相同,代码如下:

@Configuration
@EnableWebSecurity
@EnableOAuth2Client
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private ClientRegistrationRepository clientRegistrationRepository;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/login**").permitAll().anyRequest().authenticated().and().oauth2Login();
    }

    @Override
    protected void configure(OAuth2ClientAuthenticationProcessingFilter filter) throws Exception {
        super.configure(filter);
        filter.setAuthenticationSuccessHandler(new OAuth2SuccessHandler());
        filter.setApplicationEventPublisher(applicationEventPublisher);
    }

    @Bean
    public WebClient webClient(ClientRegistrationRepository clientRegistrations) {
        ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 = new ServletOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, new DefaultOAuth2AuthorizedClientManager(clientRegistrations));
        oauth2.setDefaultClientRegistrationId("demo-client");
        return WebClient.builder().filter(oauth2).build();
    }

    @Bean
    public OAuth2AuthorizedClientRepository authorizedClientRepository() {
        return new HttpSessionOAuth2AuthorizedClientRepository();
    }

    @Bean
    public AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository() {
        return new HttpSessionOAuth2AuthorizationRequestRepository();
    }

}

结语

本篇博客介绍了OAuth2.0认证登录服务端的实现过程,主要针对授权码模式和简化模式做了详细介绍。OAuth2.0是目前业界广泛使用的认证授权框架,在实际应用中,可以根据系统需求选择不同的授权方式。

猜你喜欢

转载自blog.csdn.net/u010048119/article/details/130506784