学习使用Spring Boot和Spring Security实现基于OAuth2的登录功能。我们将大致了解如何使用第三方授权服务器(例如Github、Twitter和Facebook)应用OAuth2认证。
目录
1.OAuth2架构
OAuth 2被称为一个授权框架,其主要目的是允许第三方网站或应用程序访问资源。有时人们把OAuth2称为 SSO认证的委托协议。
SSO在一个组织中特别有用,因为用户需要对多个应用程序进行认证。对我们来说,记住多个密码是一种挑战,对组织来说,管理多套凭证也是一种挑战。OAuth2有助于将凭证管理的责任隔离给独立的授权服务器。
通俗地说,单点登录(SSO)安全应用程序是指我们通过授权服务器进行认证,然后应用程序使用刷新令牌让我们保持登录状态。
在本教程中,我们将使用Github作为授权服务器,使用用户提供的凭证来验证用户的身份。
请注意,在我们的案例中,Github也将提供用户的基本信息,所以它也是作为一个资源服务器,允许我们检索用户的详细信息。
2.2.依赖性
为了在Spring boot应用程序中集成基于oauth2的授权,我们需要导入spring-boot-starter-oauth2-client模块。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
在非Boot项目中,我们需要添加spring-security-oauth2-client和spring-security-oauth2-jose依赖项。
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
<version>5.7.1</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
<version>5.7.1</version>
</dependency>
3.OAuth2客户端配置
Spring boot支持许多流行的oauth2认证提供者,只需简单的属性配置。我们只需要在注册完我们的应用程序后,从提供商那里获得客户端ID和客户端秘密令牌。
3.1.向提供商注册自定义OAuth2应用程序
我们需要创建一个oauth2登录应用程序到认证提供者的应用程序中,例如,Github、谷歌或Facebook。请注意,我们可以在一个应用程序中配置多个oauth2提供商。
例如,在Github中,我们创建一个应用程序,如下所示。
应用程序创建后,记下生成的客户端ID和客户端秘密。
3.2.配置客户端标识和客户端秘密
在我们的客户端应用程序方面,Spring boot提供商在检测到oauth2提供商的相应属性时是明智的默认值。这些属性名称有助于区分多个提供者的客户端ID和秘密。
spring.security.oauth2.client.registration.github.client-id=git-id
spring.security.oauth2.client.registration.github.client-secret=git-secret
spring.security.oauth2.client.registration.google.client-id=google-id
spring.security.oauth2.client.registration.google.client-secret=google-secret
spring.security.oauth2.client.registration.facebook.client-id=facebook-id
spring.security.oauth2.client.registration.facebook.client-secret=facebook-secret
spring.security.oauth2.client.registration.okta.client-id=okta-id
spring.security.oauth2.client.registration.okta.client-secret=okta-secret
当我们添加至少一个oauth2客户端时,spring boot将启用Oauth2ClientAutoConfiguration
类并设置所有必要的bean。
在实际应用中,客户端id和secret应该从安全的配置源或数据库中获得,我们不应该在源代码中直接写入凭证。
4.默认配置和登录页面
默认情况下,如果我们不提供任何自定义的登录页面或逻辑,只需添加上述属性就可以为spring安全模块生成的默认登录页面提供服务,它将呈现属性文件中配置的登录选项。
默认安全相当于只配置了http.oauth2Login()
方法。*oauth2Login()*方法将OAuth2LoginAuthenticationFilter
添加到过滤器链中,拦截请求并应用OAuth 2认证逻辑。
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login();
}
}
Spring Security使用**ClientRegistration
** 接口来表示应用程序中的Oauth2提供者注册细节。为了使提供者能够正常工作,spring-security必须有以下信息。
- 客户端ID和秘密
- 用于认证的授予类型
- 重定向URI
- 作用域
Spring安全自动配置在枚举 CommonOAuth2Provider
,为以下内置的提供者提供了大部分这些细节。
- 谷歌
- GitHub
- 奥克塔
要注册一个非内置的提供者,我们需要自己定义所有的配置元素。
5.注册ClientRegistrationRepository
ClientRegistrationRepository被OAuth2LoginAuthenticationFilter用来获取配置的ClientRegistration类型。如果我们不使用属性配置,那么我们需要在Java配置中定义它。
ClientRegistrationRepository与*UserDetailsService接口非常相似,有助于在典型的基于用户名-密码的登录表单中通过用户名找到UserDetails
。它通过其注册ID找到ClientRegistration*。
Spring Security提供InMemoryClientRegistrationRepository,在内存中存储ClientRegistration
的实例。
@Bean
public ClientRegistrationRepository clientRepository() {
ClientRegistration githubRegistration =
CommonOAuth2Provider.GITHUB.getBuilder("github")
.clientId("id")
.clientSecret("secret")
.build();
ClientRegistration facebookRegistration =
CommonOAuth2Provider.FACEBOOK.getBuilder("facebook")
.clientId("id")
.clientSecret("secret")
.build();
return new InMemoryClientRegistrationRepository(githubRegistration,
facebookRegistration);
}
6.自定义OAuth2配置
尽管Spring boot为所有的OAuth2配置元素提供了合理的默认值,但我们可以根据具体的要求定制特定的部分。
6.1.自定义登录页面
spring security生成的默认登录页面对于POC和入门来说已经足够好了。但对于一个生产级的应用程序,我们需要有一个与应用程序其他部分主题相匹配的自定义登录页面。
为了创建一个自定义的登录页面,我们需要提供http元素的*loginPage()*方法,如下所示。
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login()
.loginPage("/login");
}
现在我们需要为URL*/login*创建一个处理方法,为登录页面呈现自定义的HTML。
@Controller
public class LoginController {
@GetMapping("/login")
public String login() {
return "oauth2-login.html";
}
}
登录页面的HTML可以根据需求来创建。
<!doctype html>
<html lang="en">
<body>
<div class="container">
<h3>OAuth2 Login Demo</h3>
<p>Login to HowToDoInJava:</p>
<div>
<div>
With GitHub: <a href="/oauth2/authorization/github">click here</a>
</div>
<div>
With Google: <a href="/oauth2/authorization/google">click here</a>
</div>
<div>
With Facebook: <a href="/oauth2/authorization/facebook">click here</a>
</div>
</div>
</div>
</body>
</html>
6.2.处理登录成功和失败
为了控制认证后显示哪一个页面,我们有两个选择。
- 提供登录和失败的URLs作为*defaultSuccessUrl()和failationUrl()*方法
- 在successHandler()和failureHandler()方法中提供自定义逻辑,或者定义AuthenticationSuccessHandler和AuthenticationFailureHandler 类型的豆子。
提供登录成功和失败的URL很简单。
.oauth2Login()
.defaultSuccessUrl("/home")
.failureUrl("/login");
处理程序更适合于执行自定义逻辑,如审核认证信息,然后将请求转发到相应的URL。
@Bean
AuthenticationSuccessHandler authenticationSuccessHandler() {
return new CustomAuthenticationSuccessHandler();
}
@Bean
AuthenticationFailureHandler authenticationFailureHandler() {
return new CustomAuthenticationFailureHandler();
}
7.演示
为了快速演示,在*http://localhost:8080/login*URL上加载登录页面。它将显示所有配置的OAuth2提供者。
现在点击Github的链接,它将重定向到Github门户的登录页面。
一旦我们输入正确的凭证,我们将被重定向到授权访问页面。
最后,我们允许访问,浏览器将被重定向到我们应用程序的安全主页。因为现在用户已经被认证和授权,他可以在没有任何访问拒绝的错误下访问主页。
8.结语
在这个Spring安全教程中,我们学习了如何在Spring boot应用程序中配置基于OAuth2授权的登录安全。我们学习了默认应用的Oauth安全,以及自定义OAuth配置的各种元素。
我们还学会了创建一个自定义的登录页面,并使用自定义处理程序处理成功和失败的情况。
学习愉快!!
这个帖子有帮助吗?
如果你喜欢这个帖子,请告诉我们。这是我们能够改进的唯一方法。
有
没有