长沙网站优化诊断,建设网站有几种渠道,做学术用的网站,适合做外链的网站一、概述
HttpSecurity.oauth2Login() 为定制OAuth 2.0登录提供了大量的配置选项。主要的配置选项被分组到它们的协议端点对应处。
例如#xff0c;oauth2Login().authorizationEndpoint() 允许配置授权端点#xff0c;而 oauth2Login().tokenEndpoint() 允许配置令牌端点。…一、概述
HttpSecurity.oauth2Login() 为定制OAuth 2.0登录提供了大量的配置选项。主要的配置选项被分组到它们的协议端点对应处。
例如oauth2Login().authorizationEndpoint() 允许配置授权端点而 oauth2Login().tokenEndpoint() 允许配置令牌端点。
下面的代码是一个例子。
Advanced OAuth2 Login Configuration
Java
Configuration
EnableWebSecurity
public class OAuth2LoginSecurityConfig {Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.oauth2Login(oauth2 - oauth2.authorizationEndpoint(authorization - authorization...).redirectionEndpoint(redirection - redirection...).tokenEndpoint(token - token...).userInfoEndpoint(userInfo - userInfo...));return http.build();}
}
oauth2Login() DSL的主要目标是与规范中定义的命名紧密结合。
OAuth 2.0授权框架对 协议端点 的定义如下。
授权过程使用两个授权服务器端点HTTP资源。
授权端点。由客户端使用通过用户代理重定向从资源所有者那里获得授权。令牌端点。由客户端使用以交换授权许可的访问令牌通常是客户端认证。
授权过程也使用一个客户端点。
重定向端点。由授权服务器使用通过资源所有者的用户代理将包含授权凭证的响应返回给客户端。
OpenID Connect Core 1.0 规范对 UserInfo端点 的定义如下。
UserInfo端点是一个OAuth 2.0保护资源用于返回关于已认证最终用户的请求。为了获得关于最终用户的请求客户端通过使用通过OpenID连接认证获得的访问令牌向UserInfo端点提出请求。这些请求通常由一个JSON对象表示该对象包含请求的key/value对的集合。
下面的代码显示了 oauth2Login() DSL可用的完整配置选项。
OAuth2 Login Configuration Options
Java
Configuration
EnableWebSecurity
public class OAuth2LoginSecurityConfig {Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.oauth2Login(oauth2 - oauth2.clientRegistrationRepository(this.clientRegistrationRepository()).authorizedClientRepository(this.authorizedClientRepository()).authorizedClientService(this.authorizedClientService()).loginPage(/login).authorizationEndpoint(authorization - authorization.baseUri(this.authorizationRequestBaseUri()).authorizationRequestRepository(this.authorizationRequestRepository()).authorizationRequestResolver(this.authorizationRequestResolver())).redirectionEndpoint(redirection - redirection.baseUri(this.authorizationResponseBaseUri())).tokenEndpoint(token - token.accessTokenResponseClient(this.accessTokenResponseClient())).userInfoEndpoint(userInfo - userInfo.userAuthoritiesMapper(this.userAuthoritiesMapper()).userService(this.oauth2UserService()).oidcUserService(this.oidcUserService())));return http.build();}
}
除了 oauth2Login() DSL还支持XML配置。
下面的代码显示了 security namespace 中可用的完整配置选项。
OAuth2 Login XML Configuration Options
httpoauth2-login client-registration-repository-refclientRegistrationRepositoryauthorized-client-repository-refauthorizedClientRepositoryauthorized-client-service-refauthorizedClientServiceauthorization-request-repository-refauthorizationRequestRepositoryauthorization-request-resolver-refauthorizationRequestResolveraccess-token-response-client-refaccessTokenResponseClientuser-authorities-mapper-refuserAuthoritiesMapperuser-service-refoauth2UserServiceoidc-user-service-refoidcUserServicelogin-processing-url/login/oauth2/code/*login-page/loginauthentication-success-handler-refauthenticationSuccessHandlerauthentication-failure-handler-refauthenticationFailureHandlerjwt-decoder-factory-refjwtDecoderFactory/
/http
下面几节将更详细地介绍每个可用的配置选项。
OAuth 2.0 登录页面重定向端点UserInfo端点ID Token 签名验证OpenID Connect 1.0 注销
二、OAuth 2.0 登录页面
默认情况下OAuth 2.0登录页面是由 DefaultLoginPageGeneratingFilter 自动生成的。默认的登录页面显示每个配置的OAuth客户端其 ClientRegistration.clientName 为链接能够启动授权请求或OAuth 2.0登录。 对于 DefaultLoginPageGeneratingFilter 显示配置的OAuth客户端的链接注册的 ClientRegistrationRepository 需要同时实现 IterableClientRegistration。请参考 InMemoryClientRegistrationRepository。
每个OAuth客户端的链接的目的地默认为以下内容。
OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI /{registrationId}
下面一行是一个例子。
a href/oauth2/authorization/googleGoogle/a
要覆盖默认的登录页面请配置 oauth2Login().loginPage() 和可选 oauth2Login().authorizationEndpoint().baseUri()。
下面的列表显示了一个例子。
OAuth2 Login Page Configuration
Java
Configuration
EnableWebSecurity
public class OAuth2LoginSecurityConfig {Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.oauth2Login(oauth2 - oauth2.loginPage(/login/oauth2)....authorizationEndpoint(authorization - authorization.baseUri(/login/oauth2/authorization)...));return http.build();}
} 你需要提供一个带有 RequestMapping(/login/oauth2) 的 Controller能够渲染自定义的登录页面。 如前所述配置 oauth2Login().authorizationEndpoint().baseUri() 是可选的。但是如果你选择自定义请确保每个OAuth客户端的链接与 authorizationEndpoint().baseUri() 相匹配。 下面一行显示了一个例子。 a href/login/oauth2/authorization/googleGoogle/a
三、重定向端点
重定向端点由授权服务器使用用于通过资源所有者用户代理向客户返回授权响应包含授权凭证 OAuth 2.0登录利用的是授权码授予。因此授权凭证就是授权码。
默认的授权响应 baseUri重定向端点是 /login/oauth2/code/*这在 OAuth2LoginAuthenticationFilter.DEFAULT_FILTER_PROCESSES_URI 中定义。
如果你想定制授权响应 baseUri请按以下方式配置。
Redirection Endpoint Configuration
Java
Configuration
EnableWebSecurity
public class OAuth2LoginSecurityConfig {Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.oauth2Login(oauth2 - oauth2.redirectionEndpoint(redirection - redirection.baseUri(/login/oauth2/callback/*)...));return http.build();}
} 你还需要确保 ClientRegistration.redirectUri 与自定义授权响应 baseUri 相匹配。 下面的列表显示了一个例子。 Javareturn CommonOAuth2Provider.GOOGLE.getBuilder(google).clientId(google-client-id).clientSecret(google-client-secret).redirectUri({baseUrl}/login/oauth2/callback/{registrationId}).build();
四、UserInfo端点
UserInfo端点包括一些配置选项在下面的小节中描述。
映射用户权限OAuth 2.0 UserServiceOpenID Connect 1.0 UserService
1、映射用户权限
在用户成功通过 OAuth 2.0 提供商的认证后OAuth2User.getAuthorities()或 OidcUser.getAuthorities()包含一个由 OAuth2UserRequest.getAccessToken().getScopes() 填充的授予权限列表其前缀为 SCOPE_。这些授权可以被映射到一组新的 GrantedAuthority 实例中在完成认证时提供给 OAuth2AuthenticationToken。 OAuth2AuthenticationToken.getAuthorities() 用于授权请求如 hasRole(USER) 或 hasRole(ADMIN) 中。
在映射用户权限时有几个选项可以选择。
使用 GrantedAuthoritiesMapper基于Delegation的策略与OAuth2UserService
2、使用 GrantedAuthoritiesMapper
GrantedAuthoritiesMapper 被赋予一个授予权限的列表其中包含一个类型为 OAuth2UserAuthority 和权限字符串 OAUTH2_USER或 OidcUserAuthority 和权限字符串 OIDC_USER的特殊权限。
提供一个 GrantedAuthoritiesMapper 的实现并对其进行配置如下所示。
Granted Authorities Mapper Configuration
Java
Configuration
EnableWebSecurity
public class OAuth2LoginSecurityConfig {Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.oauth2Login(oauth2 - oauth2.userInfoEndpoint(userInfo - userInfo.userAuthoritiesMapper(this.userAuthoritiesMapper())...));return http.build();}private GrantedAuthoritiesMapper userAuthoritiesMapper() {return (authorities) - {SetGrantedAuthority mappedAuthorities new HashSet();authorities.forEach(authority - {if (OidcUserAuthority.class.isInstance(authority)) {OidcUserAuthority oidcUserAuthority (OidcUserAuthority)authority;OidcIdToken idToken oidcUserAuthority.getIdToken();OidcUserInfo userInfo oidcUserAuthority.getUserInfo();// Map the claims found in idToken and/or userInfo// to one or more GrantedAuthoritys and add it to mappedAuthorities} else if (OAuth2UserAuthority.class.isInstance(authority)) {OAuth2UserAuthority oauth2UserAuthority (OAuth2UserAuthority)authority;MapString, Object userAttributes oauth2UserAuthority.getAttributes();// Map the attributes found in userAttributes// to one or more GrantedAuthoritys and add it to mappedAuthorities}});return mappedAuthorities;};}
}
或者你可以注册一个 GrantedAuthoritiesMapper Bean让它自动应用于配置如下所示。
Granted Authorities Mapper Bean Configuration
Java
Configuration
EnableWebSecurity
public class OAuth2LoginSecurityConfig {Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.oauth2Login(withDefaults());return http.build();}Beanpublic GrantedAuthoritiesMapper userAuthoritiesMapper() {...}
}
3、基于Delegation的策略与OAuth2UserService
与使用 GrantedAuthoritiesMapper 相比这种策略是先进的。然而它也更灵活因为它让你可以访问 OAuth2UserRequest 和 OAuth2User当使用OAuth 2.0 UserService或 OidcUserRequest 和 OidcUser当使用 OpenID Connect 1.0 UserService。
OAuth2UserRequest和 OidcUserRequest为你提供了对相关 OAuth2AccessToken 的访问这在 delegator 需要从受保护的资源中获取权限信息然后再为用户映射自定义权限的情况下非常有用。
下面的例子显示了如何使用OpenID Connect 1.0 UserService实现和配置基于delegation的策略。
OAuth2UserService Configuration
Java
Configuration
EnableWebSecurity
public class OAuth2LoginSecurityConfig {Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.oauth2Login(oauth2 - oauth2.userInfoEndpoint(userInfo - userInfo.oidcUserService(this.oidcUserService())...));return http.build();}private OAuth2UserServiceOidcUserRequest, OidcUser oidcUserService() {final OidcUserService delegate new OidcUserService();return (userRequest) - {// Delegate to the default implementation for loading a userOidcUser oidcUser delegate.loadUser(userRequest);OAuth2AccessToken accessToken userRequest.getAccessToken();SetGrantedAuthority mappedAuthorities new HashSet();// TODO// 1) Fetch the authority information from the protected resource using accessToken// 2) Map the authority information to one or more GrantedAuthoritys and add it to mappedAuthorities// 3) Create a copy of oidcUser but use the mappedAuthorities insteadoidcUser new DefaultOidcUser(mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo());return oidcUser;};}
}
4、OAuth 2.0 UserService
DefaultOAuth2UserService 是一个 OAuth2UserService 的实现支持标准的OAuth2.0提供者。 OAuth2UserService 从 UserInfo 端点获取最终用户资源所有者的用户属性通过使用授权流程中授予客户端的访问令牌并以 OAuth2User 的形式返回一个 AuthenticatedPrincipal。
DefaultOAuth2UserService 在UserInfo端点请求用户属性时使用 RestOperations 实例。
如果你需要定制UserInfo请求的预处理你可以为 DefaultOAuth2UserService.setRequestEntityConverter() 提供一个自定义的 ConverterOAuth2UserRequest, RequestEntity?。默认的实现 OAuth2UserRequestEntityConverter 建立了一个UserInfo请求的 RequestEntity 表示默认在授权header中设置 OAuth2AccessToken。
在另一端如果你需要定制 UserInfo 响应的后处理你需要为 DefaultOAuth2UserService.setRestOperations() 提供一个自定义配置的 RestOperations。默认的 RestOperations 配置如下。
RestTemplate restTemplate new RestTemplate();
restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
OAuth2ErrorResponseErrorHandler 是一个 ResponseErrorHandler可以处理OAuth2.0错误400 Bad Request。它使用一个 OAuth2ErrorHttpMessageConverter 将 OAuth2.0 错误参数转换为 OAuth2Error。
无论你是定制 DefaultOAuth2UserService 还是提供你自己的 OAuth2UserService 的实现你都需要按以下方式进行配置。
Java
Configuration
EnableWebSecurity
public class OAuth2LoginSecurityConfig {Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.oauth2Login(oauth2 - oauth2.userInfoEndpoint(userInfo - userInfo.userService(this.oauth2UserService())...));return http.build();}private OAuth2UserServiceOAuth2UserRequest, OAuth2User oauth2UserService() {...}
}
5、OpenID Connect 1.0 UserService
OidcUserService 是一个 OAuth2UserService 的实现支持OpenID Connect 1.0提供者。
OidcUserService 在 UserInfo 端点请求用户属性时利用了 DefaultOAuth2UserService。
如果你需要定制UserInfo请求的预处理或UserInfo响应的后处理你需要向 OidcUserService.setOauth2UserService() 提供一个自定义配置的 DefaultOAuth2UserService。
无论你是定制 OidcUserService 还是为 OpenID Connect 1.0 提供商提供自己的 OAuth2UserService 实现你都需要按以下方式配置它。
Java
Configuration
EnableWebSecurity
public class OAuth2LoginSecurityConfig {Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.oauth2Login(oauth2 - oauth2.userInfoEndpoint(userInfo - userInfo.oidcUserService(this.oidcUserService())...));return http.build();}private OAuth2UserServiceOidcUserRequest, OidcUser oidcUserService() {...}
}
五、ID Token 签名验证
OpenID Connect 1.0认证引入了 ID Token它是一个安全令牌包含授权服务器在客户端使用时对终端用户进行认证的要求。
ID令牌被表示为 JSON Web TokenJWT并且必须使用 JSON Web Signature JWS进行签名。
OidcIdTokenDecoderFactory 提供一个用于 OidcIdToken 签名验证的 JwtDecoder。默认算法是 RS256但在客户端注册时分配的算法可能不同。对于这些情况你可以配置解析器以返回为特定客户分配的预期 JWS 算法。
JWS算法解析器是一个 Function它接受 ClientRegistration 并返回客户端预期的 JwsAlgorithm例如 SignatureAlgorithm.RS256 或 MacAlgorithm.HS256。
下面的代码显示了如何配置 OidcIdTokenDecoderFactory Bean 为所有 ClientRegistration 实例默认为 MacAlgorithm.HS256。
Java
Bean
public JwtDecoderFactoryClientRegistration idTokenDecoderFactory() {OidcIdTokenDecoderFactory idTokenDecoderFactory new OidcIdTokenDecoderFactory();idTokenDecoderFactory.setJwsAlgorithmResolver(clientRegistration - MacAlgorithm.HS256);return idTokenDecoderFactory;
} 对于基于MAC的算法如 HS256、HS384 或 HS512与 client-id 对应的 client-secret 被用作签名验证的对称密钥。 如果为 OpenID Connect 1.0 认证配置了一个以上的 ClientRegistrationJWS 算法解析器可以评估所提供的 ClientRegistration 来决定返回哪种算法。
六、OpenID Connect 1.0 注销
OpenID Connect会话管理1.0允许通过使用客户端在提供方注销终端用户的能力。其中一个可用的策略是 RP发起的注销。
如果OpenID提供商同时支持会话管理和 Discovery客户端可以从OpenID提供商的 Discovery Metadata 中获得 end_session_endpoint URL。你可以通过在 ClientRegistration 中配置 issuer-uri 来做到这一点如下所示。
spring:security:oauth2:client:registration:okta:client-id: okta-client-idclient-secret: okta-client-secret...provider:okta:issuer-uri: https://dev-1234.oktapreview.com
另外你可以配置 OidcClientInitiatedLogoutSuccessHandler它实现了RP发起的注销如下所示。
Java
Configuration
EnableWebSecurity
public class OAuth2LoginSecurityConfig {Autowiredprivate ClientRegistrationRepository clientRegistrationRepository;Beanpublic SecurityFilterChain filterChain(HttpSecurity http) throws Exception {http.authorizeHttpRequests(authorize - authorize.anyRequest().authenticated()).oauth2Login(withDefaults()).logout(logout - logout.logoutSuccessHandler(oidcLogoutSuccessHandler()));return http.build();}private LogoutSuccessHandler oidcLogoutSuccessHandler() {OidcClientInitiatedLogoutSuccessHandler oidcLogoutSuccessHandler new OidcClientInitiatedLogoutSuccessHandler(this.clientRegistrationRepository);// Sets the location that the End-Users User Agent will be redirected to// after the logout has been performed at the ProvideroidcLogoutSuccessHandler.setPostLogoutRedirectUri({baseUrl});return oidcLogoutSuccessHandler;}
} OidcClientInitiatedLogoutSuccessHandler 支持 {baseUrl} 占位符。 如果使用应用程序的基本URL如 app.example.org将在请求时替换它。