南通高端网站,海外购物app排行,温州专业微网站制作公司,羽毛球赛事奖金文章目录 1. 授权服务器2. 授权类型1. Password (密码模式)2. Refresh Token#xff08;刷新令牌#xff09;3. Client Credentials#xff08;客户端凭证模式#xff09; 3. AuthorizationServerConfigurerAdapter4. 自定义 TokenStore 管理令牌1. TokenStore 的作用2. Cu… 文章目录 1. 授权服务器2. 授权类型1. Password (密码模式)2. Refresh Token刷新令牌3. Client Credentials客户端凭证模式 3. AuthorizationServerConfigurerAdapter4. 自定义 TokenStore 管理令牌1. TokenStore 的作用2. CustomAuthenticationKeyGenerator3. CustomRedisTokenStore4. TokenStoreAutoConfiguration 5. 自定义 UserDetailsService 获取认证用户信息1. UserDetailsService 的作用2. CustomUserDetailService3. 密码加密配置类 PasswordEncodeConfig4. 配置 CustomUserDetailService 6. 配置授权服务器7. 启动项目测试获取访问令牌 1. 授权服务器
Spring Security OAuth2 授权服务器的作用是为各种客户端应用如Web应用、移动应用、微服务等提供一个集中式的身份认证和授权服务。授权服务器的主要功能是颁发、管理和验证访问令牌Access Token和刷新令牌Refresh Token从而确保只有经过授权的客户端才能访问受保护的资源。
1.管理客户端应用
授权服务器允许你注册和管理不同的客户端应用程序例如Web应用、移动应用、API客户端。对于每个客户端应用授权服务器会为其分配一个唯一的客户端IDClient ID和客户端密钥Client Secret并定义其授权范围和访问权限。
2. 颁发访问令牌
授权服务器的核心功能之一是颁发访问令牌。当客户端应用请求访问受保护的资源时它需要先向授权服务器请求一个访问令牌。授权服务器会根据预定义的授权流程如授权码模式、密码模式等验证客户端的身份和权限然后颁发一个访问令牌给客户端。客户端可以使用这个访问令牌来访问资源服务器上的受保护资源。
3. 支持多种授权模式
① 密码模式适用于用户信任的应用如移动应用直接使用用户名和密码获取访问令牌。
② 客户端凭据模式适用于服务之间的通信不涉及用户直接使用客户端凭据获取访问令牌。
③ 刷新令牌在访问令牌过期时客户端可以使用刷新令牌获取新的访问令牌避免用户重复登录。
4. 验证访问令牌
授权服务器不仅颁发访问令牌还负责验证访问令牌的有效性。资源服务器在收到客户端请求时可以通过调用授权服务器的令牌检查接口如 /oauth/check_token来验证访问令牌的合法性和有效期从而确保请求者的身份和权限。
5. 管理用户身份和权限
授权服务器与用户身份管理系统如用户数据库、LDAP等集成负责用户的认证和权限管理。当客户端应用请求访问令牌时授权服务器会验证用户的身份并根据用户的角色或权限决定是否颁发访问令牌以及授予哪些权限。
2. 授权类型
OAuth2 授权框架提供了多种授权类型允许客户端以不同的方式获取访问令牌。每种授权类型都有不同的使用场景和适用条件。
1. Password (密码模式)
密码模式适用于在信任的应用程序中直接向 OAuth2 授权服务器提供用户的用户名和密码。这种模式适用于移动应用或服务器端应用直接与授权服务器交互的场景。用户直接将用户名和密码提供给客户端客户端使用这些凭据向授权服务器请求访问令牌。
使用步骤
① 用户提供用户名和密码 用户将其用户名和密码输入到客户端应用中。
② 客户端请求访问令牌 客户端使用用户名、密码、客户端ID和客户端密钥向授权服务器请求访问令牌。
POST /oauth/token HTTP/1.1
Host: authorization-server.com
Authorization: Basic Base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencodedgrant_typepasswordusernameuserpasswordpassscoperead③ 服务器返回访问令牌 授权服务器验证凭据后返回访问令牌。
{access_token: abcdefg12345,token_type: bearer,expires_in: 3600,refresh_token: refresh12345
}2. Refresh Token刷新令牌
刷新令牌用于获取新的访问令牌而无需用户重新进行认证。这种模式通常与其他授权模式结合使用例如密码模式或授权码模式。当访问令牌过期后需要获取新的访问令牌时使用刷新令牌。适用于需要长期保持用户会话的应用例如 Web 应用或移动应用。
使用步骤
① 客户端使用刷新令牌请求新访问令牌 当访问令牌过期时客户端使用刷新令牌向授权服务器请求新的访问令牌。
POST /oauth/token HTTP/1.1
Host: authorization-server.com
Authorization: Basic Base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencodedgrant_typerefresh_tokenrefresh_tokenrefresh12345② 服务器返回新的访问令牌 授权服务器验证刷新令牌后返回新的访问令牌。
{access_token: newabcdefg12345,token_type: bearer,expires_in: 3600,refresh_token: newrefresh12345
}3. Client Credentials客户端凭证模式
客户端凭证模式不涉及用户客户端自身以其身份请求访问令牌。这种模式常用于服务端与服务端之间的通信例如 API 网关与微服务之间的通信。适用于应用之间的服务调用通常在后台系统中使用。用于访问与用户无关的资源或使用应用本身的权限访问资源。
使用步骤
① 客户端请求访问令牌 客户端使用自己的客户端ID和客户端密钥向授权服务器请求访问令牌。
bash复制代码POST /oauth/token HTTP/1.1
Host: authorization-server.com
Authorization: Basic Base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencodedgrant_typeclient_credentialsscoperead② 服务器返回访问令牌 授权服务器验证客户端凭证后返回访问令牌。
{access_token: clienttoken12345,token_type: bearer,expires_in: 3600
}3. AuthorizationServerConfigurerAdapter
public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer {Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {}Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {}Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {}}1. configure(AuthorizationServerSecurityConfigurer security)
用于配置授权服务器的安全性如 /oauth/token、/oauth/authorize 等端点的安全性配置:
Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {// 允许客户端表单身份验证security.allowFormAuthenticationForClients()// 允许所有人访问令牌验证端点.checkTokenAccess(permitAll())// 仅允许认证后的用户访问密钥端点.tokenKeyAccess(isAuthenticated());
}2. configure(ClientDetailsServiceConfigurer clients) 方法
用于配置客户端详细信息服务这个服务用来定义哪些客户端可以访问授权服务器以及客户端的配置信息。
Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {// 将客户端信息存储在内存中clients.inMemory()// 定义客户端 ID.withClient(client-id)// 定义客户端密钥.secret(passwordEncoder.encode(client-secret))// 定义客户端支持的授权模式.authorizedGrantTypes(authorization_code, password, refresh_token, client_credentials)// 定义客户端的作用范围.scopes(read, write)// 设置访问令牌的有效期.accessTokenValiditySeconds(3600)// 设置刷新令牌的有效期.refreshTokenValiditySeconds(7200);
}3. configure(AuthorizationServerEndpointsConfigurer endpoints) 方法
用于配置授权和令牌的端点以及令牌服务、令牌存储、用户认证等相关配置。
Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {// 配置用于密码模式的 AuthenticationManagerendpoints.authenticationManager(authenticationManager)// 在刷新令牌时使用此服务加载用户信息.userDetailsService(userDetailsService)// 配置令牌的存储策略例如内存、数据库或 Redis.tokenStore(new InMemoryTokenStore());
}4. 自定义 TokenStore 管理令牌
1. TokenStore 的作用
TokenStore 是 Spring Security OAuth2 中用于管理 OAuth2 令牌Access Token 和 Refresh Token的接口。它的主要作用是定义如何生成、存储、读取和删除令牌。TokenStore 的具体实现类决定了令牌的存储方式例如存储在内存中、数据库中、Redis 中或以 JWT 的形式进行编码。TokenStore 的主要作用
① 生成和存储令牌当客户端请求令牌时TokenStore 负责生成访问令牌和刷新令牌并将它们存储在指定的存储介质中如内存、数据库、Redis 等。
② 读取令牌TokenStore 允许根据令牌的值查找和读取存储的令牌。这个功能在资源服务器或授权服务器验证令牌时非常重要。
③ 删除令牌TokenStore 也提供了删除令牌的方法例如在用户注销或令牌过期时授权服务器可以删除对应的访问令牌和刷新令牌。
④ 管理令牌的生命周期TokenStore 负责管理令牌的生命周期包括过期时间、刷新操作等。它可以确保访问令牌和刷新令牌在其有效期内使用并在适当的时候自动过期。
当客户端请求令牌时授权服务器通过 TokenStore 生成并存储令牌。客户端在后续请求中携带令牌访问受保护的资源时资源服务器通过 TokenStore 验证令牌的有效性。TokenStore 管理整个令牌生命周期包括生成、存储、读取、刷新和删除等操作。
Bean
public TokenStore tokenStore(RedisConnectionFactory redisConnectionFactory) {return new RedisTokenStore(redisConnectionFactory);
}2. CustomAuthenticationKeyGenerator
在 OAuth2 的认证过程中DefaultAuthenticationKeyGenerator 通常用于生成唯一的认证键AuthenticationKey该键用于标识客户端的认证请求。默认情况下DefaultAuthenticationKeyGenerator 会基于客户端的 ID、授权类型、作用域等信息生成一个哈希值作为认证请求的唯一标识。
CustomAuthenticationKeyGenerator 类通过在原有的键生成逻辑上添加一个随机值 UUID.randomUUID().toString() 来确保每次调用时生成的键都是唯一的即使所有其他参数都相同。这种方法增加了键的随机性避免了重复的认证请求生成相同的键。
public class CustomAuthenticationKeyGenerator extends DefaultAuthenticationKeyGenerator {private static final String RAND keyGeneratorRand;Overrideprotected String generateKey(MapString, String values) {// 加入一个随机的要素,保证每次调用时生成的们的hash都不一样values.put(RAND, UUID.randomUUID().toString());return super.generateKey(values);}
}3. CustomRedisTokenStore
CustomRedisTokenStore 是一个自定义的令牌存储类继承自 RedisTokenStore。RedisTokenStore 是 Spring Security OAuth2 提供的一个实现用于将 OAuth2 的访问令牌和刷新令牌存储在 Redis 中。
/*** 自定义的RedisTokenStore处理*/
public class CustomRedisTokenStore extends RedisTokenStore {public CustomRedisTokenStore(RedisConnectionFactory connectionFactory) {super(connectionFactory);}// 从 Redis 中读取并返回对应的访问令牌Overridepublic OAuth2AccessToken readAccessToken(String tokenValue) {return super.readAccessToken(tokenValue);}// 从 Redis 中移除指定的访问令牌Overridepublic void removeAccessToken(OAuth2AccessToken accessToken) {super.removeAccessToken(accessToken);}// 使用刷新令牌来删除关联的访问令牌Overridepublic void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) {super.removeAccessTokenUsingRefreshToken(refreshToken);}
}4. TokenStoreAutoConfiguration
Configuration
public class TokenStoreAutoConfiguration {Autowiredprivate RedisConnectionFactory connectionFactory;Beanpublic TokenStore tokenStore() {// 使用redis存储tokenRedisTokenStore redisTokenStore new CustomRedisTokenStore(connectionFactory);redisTokenStore.setAuthenticationKeyGenerator(new CustomAuthenticationKeyGenerator());return redisTokenStore;}
}5. 自定义 UserDetailsService 获取认证用户信息
1. UserDetailsService 的作用
UserDetailsService 是 Spring Security 中的一个核心接口用于根据用户名获取用户的详细信息。这个接口通常用于处理用户身份验证过程中的用户查找逻辑。具体来说当用户试图登录应用程序时Spring Security 会使用 UserDetailsService 来加载用户信息包括用户名、密码、权限等以便进行身份验证。
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;UserDetails 是 UserDetailsService 返回的核心对象包含了用户的详细信息
public interface UserDetails extends Serializable {// 返回用户的权限角色集合Collection? extends GrantedAuthority getAuthorities();// 返回用户的密码通常是加密后的String getPassword();// 返回用户的用户名String getUsername();// 指示账户是否未过期未过期的账户可使用。boolean isAccountNonExpired();// 指示账户是否未锁定未锁定的账户可使用。boolean isAccountNonLocked();// 指示用户的凭据是否未过期未过期的凭据可使用。boolean isCredentialsNonExpired();// 指示用户是否已启用已启用的用户可使用。boolean isEnabled();
}2. CustomUserDetailService
Service
public class CustomUserDetailService implements UserDetailsService {Autowiredprivate UserDao userDao;Autowiredprivate PolicyDao policyDao;Autowiredprivate RoleDao roleDao;Overridepublic UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {// 从数据库中查找用户UserEntity userEntity userDao.queryUserByUserName(username);if (userEntity null) {throw new UsernameNotFoundException(User not found with username: username);}// 根据用户信息查询角色信息ListRoleEntity roleEntities roleDao.queryRolesByUserId(userEntity.getId());ListString roleIds roleEntities.stream().map(RoleEntity::getId).collect(Collectors.toList());// 根据角色信息查询权限信息ListPolicyEntity policyEntities policyDao.queryPolicyByRoleId(roleIds);// 查询权限名称ListString policyNames policyEntities.stream().map(PolicyEntity::getName).collect(Collectors.toList());// 构造认证用户权限信息ListSimpleGrantedAuthority grantedAuthorities policyNames.stream().map(policyName - new SimpleGrantedAuthority(policyName)).collect(Collectors.toList());// 将 UserEntity 转换为 UserDetails 对象UserDetails userDetails User.builder().username(userEntity.getUsername()).password(userEntity.getPassword()).authorities(grantedAuthorities).accountExpired(false).accountLocked(false).disabled(false).build();return userDetails ;}
}3. 密码加密配置类 PasswordEncodeConfig
Configuration
public class PasswordEncodeConfig {Beanpublic PasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}
}4. 配置 CustomUserDetailService
Configuration
EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {Autowiredprivate CustomUserDetailService userDetailsService;Autowiredprivate PasswordEncoder passwordEncoder;Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);}Overrideprotected void configure(HttpSecurity http) throws Exception {super.configure(http);}BeanOverridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}
}6. 配置授权服务器
Configuration
EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {Autowiredprivate AuthenticationManager authenticationManager;Autowiredprivate UserDetailsService userDetailsService;Autowiredprivate TokenStore tokenStore;Autowiredprivate PasswordEncoder passwordEncoder;Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {// 用于配置授权服务器的安全性如 /oauth/token、/oauth/authorize 等端点的安全性配置。// 允许客户端表单身份验证security.allowFormAuthenticationForClients()// 允许所有人访问令牌验证端点.checkTokenAccess(permitAll())// 仅允许认证后的用户访问密钥端点.tokenKeyAccess(isAuthenticated);}/*** 对于每个客户端应用授权服务器会为其分配一个唯一的客户端ID和客户端密钥并定义其授权范围和访问权限。*/Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {// 用于配置客户端详细信息服务这个服务用来定义哪些客户端可以访问授权服务器以及客户端的配置信息。// 将客户端信息存储在内存中适合开发和测试环境。clients.inMemory()// 定义客户端ID.withClient(client_id)// 定义客户端密钥.secret(passwordEncoder.encode(client_secret))// 定义客户端支持的授权模式。.authorizedGrantTypes(password,refresh_token,client_credentials)// 设置访问令牌的有效期。.accessTokenValiditySeconds(3600)// 设置刷新令牌的有效期。.refreshTokenValiditySeconds(7200)// 定义客户端的作用范围。.scopes(all);}Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {// 用于配置授权和令牌的端点以及令牌服务、令牌存储、用户认证等相关配置。// 配置用于密码模式的 AuthenticationManager。endpoints.authenticationManager(authenticationManager)// 在刷新令牌时使用此服务加载用户信息。.userDetailsService(userDetailsService)// 配置令牌的存储策略例如内存、数据库或 Redis。.tokenStore(tokenStore);}
}7. 启动项目测试获取访问令牌