2015年做那些网站致富,电脑系统网站建设,鹿泉营销型网站制作价格低,视频短链接生成器有时以前#xff0c;我们发表了一篇文章#xff0c;分享了一种在云环境中实现无状态会话的自定义方法。 今天#xff0c;让我们探讨为Spring Boot应用程序设置Oauth2身份验证的另一个流行用例。 在此示例中#xff0c;我们将使用JSON Web令牌#xff08;JWT#xff09;作… 有时以前我们发表了一篇文章分享了一种在云环境中实现无状态会话的自定义方法。 今天让我们探讨为Spring Boot应用程序设置Oauth2身份验证的另一个流行用例。 在此示例中我们将使用JSON Web令牌JWT作为Oauth2令牌的格式。 该示例部分是基于Spring Security Oauth 2的官方示例开发的。但是我们将专注于理解Oauth 2请求的原理。 源代码位于https://github.com/tuanngda/spring-boot-oauth2-demo.git 背景 Oauth2和JWT 当您要使用Oauth2和JWT时我们将不做详细介绍。 通常如果需要允许其他人为您的服务构建前端应用程序则可能需要采用Oauth。 我们专注于Oauth2和JWT因为它们是市场上最流行的身份验证框架和协议。 Spring安全Oauth 2 Spring Security Oauth2是Oauth 2的实现它是在Spring Security之上构建的Spring Security是一个非常可扩展的身份验证框架。 总体而言Spring Security包括2个基本步骤为每个请求创建一个身份验证对象并根据身份验证应用授权检查。 第一步是在多层安全筛选器中完成的。 根据配置每一层都可以帮助创建基本身份验证摘要身份验证表单身份验证或我们选择自行实现的任何自定义身份验证的身份验证。 我们在上一篇文章中构建的客户端会话是一种自定义身份验证而Spring Security Oauth 2是另一种自定义身份验证。 因为在此示例中我们的应用程序既提供令牌又使用令牌因此Spring Security Oauth 2不应是应用程序的唯一身份验证层。 我们需要另一种身份验证机制来保护令牌提供者端点。 对于集群环境令牌或签名令牌的秘密对于JWT假定是持久的但是我们跳过此步骤以简化示例。 同样用户身份验证和客户端身份都是硬编码的。 系统设计 总览 在我们的应用程序中我们需要设置3个组件 授权端点和令牌端点以帮助提供Oauth 2令牌。 WebSecurityConfigurerAdapter这是一个身份验证层其硬编码顺序为3根据Dave Syer 。 该身份验证层将为包含Oauth 2令牌的任何请求设置身份验证和委托人。 如果令牌丢失则另一种身份验证机制可以保护令牌端点和其他资源。 在此示例中我们选择基本身份验证是为了简化编写测试时的操作。 由于我们未指定顺序因此它将采用默认值100。对于Spring安全性顺序越低优先级越高 因此我们应该期望Oauth 2在FilterChainProxy中进行基本身份验证之前。 在IDE中检查证明我们的设置正确。 在上图中Oauth2AuthenticationProcessingFilter出现在BasicAuthenticationFilter的前面。 授权服务器配置 这是我们的授权和令牌端点配置 Configuration
EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {Value(${resource.id:spring-boot-application})private String resourceId;Value(${access_token.validity_period:3600})int accessTokenValiditySeconds 3600;Autowiredprivate AuthenticationManager authenticationManager;Beanpublic JwtAccessTokenConverter accessTokenConverter() {return new JwtAccessTokenConverter();}Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.authenticationManager(this.authenticationManager).accessTokenConverter(accessTokenConverter());}Overridepublic void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {oauthServer.tokenKeyAccess(isAnonymous() || hasAuthority(ROLE_TRUSTED_CLIENT)).checkTokenAccess(hasAuthority(ROLE_TRUSTED_CLIENT));}Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient(normal-app).authorizedGrantTypes(authorization_code, implicit).authorities(ROLE_CLIENT).scopes(read, write).resourceIds(resourceId).accessTokenValiditySeconds(accessTokenValiditySeconds).and().withClient(trusted-app).authorizedGrantTypes(client_credentials, password).authorities(ROLE_TRUSTED_CLIENT).scopes(read, write).resourceIds(resourceId).accessTokenValiditySeconds(accessTokenValiditySeconds).secret(secret);}
} 关于此实现没有什么值得注意的事情。 设置JWT令牌就像使用JwtAccessTokenConverter一样简单。 因为我们从未设置签名密钥所以它是随机生成的。 如果我们打算将应用程序部署到云中则必须在所有授权服务器之间同步签名密钥。 除了选择创建身份验证管理器之外我们还选择从Spring容器中注入现有的身份验证管理器。 通过此步骤我们可以与基本身份验证过滤器共享身份验证管理器。 可能有受信任的应用程序而不是受信任的应用程序。 受信任的应用程序可以有自己的秘密。 这是客户凭证授权授予所必需的。 除客户端凭据外所有其他三个授予都需要资源所有者的凭据。 我们允许匿名检查令牌端点。 使用此配置无需基本身份验证或Oauth 2令牌即可访问检查令牌。 资源服务器配置 这是我们的资源服务器配置配置 Configuration
EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {Value(${resource.id:spring-boot-application})private String resourceId;Overridepublic void configure(ResourceServerSecurityConfigurer resources) {resources.resourceId(resourceId);}Overridepublic void configure(HttpSecurity http) throws Exception {http.requestMatcher(new OAuthRequestedMatcher()).authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll().anyRequest().authenticated();}private static class OAuthRequestedMatcher implements RequestMatcher {public boolean matches(HttpServletRequest request) {String auth request.getHeader(Authorization);// Determine if the client request contained an OAuth Authorizationboolean haveOauth2Token (auth ! null) auth.startsWith(Bearer);boolean haveAccessToken request.getParameter(access_token)!null;return haveOauth2Token || haveAccessToken;}}} 这里有几件事要注意 添加了OAuthRequestedMatcher以便Oauth过滤器仅处理Oauth2请求。 我们添加了此内容以便在基本身份验证层而不是Oauth 2层将拒绝未授权的请求。 在功能方面这可能没有任何区别但出于可用性考虑我们对其进行了添加。 对于客户端他们将收到401 HTTP状态其中包含此新标头和旧标头 WWW-Authenticate基本领域“领域” 使用新的响应标头浏览器将自动提示用户输入用户名和密码。 如果您不希望任何其他身份验证机制访问该资源则无需执行此步骤。 某些浏览器例如Chrome喜欢在发出AJAX调用之前发送OPTIONS请求以查找CORS。 因此最好始终允许OPTIONS请求。 基本身份验证安全配置 如前所述因为我们需要保护令牌提供者端点。 Configuration
EnableGlobalMethodSecurity(prePostEnabled true)
EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {Autowiredpublic void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser(user).password(password).roles(USER).and().withUser(admin).password(password).roles(USER, ADMIN);}Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers(HttpMethod.OPTIONS).permitAll().anyRequest().authenticated().and().httpBasic().and().csrf().disable();}OverrideBeanpublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}
} 有几件事要注意 我们公开了AuthenticationManager bean以便我们的两个身份验证安全适配器可以共享一个身份验证管理器。 Spring Security CSRF可与JSP无缝协作但对RestAPI来说很麻烦。 因为我们希望将此示例应用程序用作用户开发自己的应用程序的基础所以我们关闭了CSRF并添加了CORS过滤器以便可以立即使用它。 测试中 我们严格按照Oauth2规范为每种授权授予类型编写了一个测试方案。 由于Spring Security Oauth 2是基于Spring Security框架的实现因此我们的兴趣转向查看如何构造基础身份验证和主体。 在总结实验结果之前让我们快速看一下要记录的内容。 对令牌提供者端点的大多数请求都是使用POST请求发送的但它们包含用户凭据作为参数。 即使为了方便起见我们将此凭据作为url的一部分放置也切勿在Oauth 2客户端中执行此操作。 我们创建了两个端点/ resources / principal和/ resources / roles来捕获Oauth 2身份验证的主体和权限。 这是我们的设置 用户 类型 当局 凭据 用户 资源所有者 ROLE_USER ÿ 管理员 资源所有者 ROLE_ADMIN ÿ 普通应用 客户 ROLE_CLIENT ñ 受信任的应用 客户 ROLE_TRUSTED_CLIENT ÿ 赠款类型 用户 客户 主要 当局 授权码 用户 普通应用 用户 ROLE_USER 客户凭证 不适用 受信任的应用 受信任的应用 没有权限 隐含的 用户 普通应用 用户 ROLE_USER 资源所有者密码凭证 用户 受信任的应用 用户 ROLE_USER 除客户端凭据外此结果与预期的相当。 有趣的是即使客户端通过客户端证书检索Oauth 2令牌批准的请求仍然没有任何客户端权限而仅具有客户端证书。 我认为这是有道理的因为隐式授予类型的令牌无法重用。 这是我们发现的 翻译自: https://www.javacodegeeks.com/2016/04/spring-oauth2-jwt-sample.html