package com.plat.config;
import com.plat.service.UserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.approval.ApprovalStore;
import org.springframework.security.oauth2.provider.approval.JdbcApprovalStore;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Arrays;
@Configuration
@EnableAuthorizationServer //OAuth2的授权服务器
public class OAuth2ServiceConfig implements AuthorizationServerConfigurer {
@Resource(name = "jwtTokenStore")
private TokenStore tokenStore; //注入自定义的token存储配置Bean
@Resource(name = "jdbcClientDetailsService")
private ClientDetailsService clientDetailsService; //客户端角色详情
@Resource
private AuthenticationManager authenticationManager; //注入安全配置类中定义的认证管理器Bean
@Resource(name = "jdbcAuthorizationCodeServices")
private AuthorizationCodeServices authorizationCodeServices; //注入自定义的授权码模式服务配置Bean
@Resource(name = "jdbcApprovalStore")
private ApprovalStore approvalStore; //授权信息保存策略
@Resource
private JwtAccessTokenConverter accessTokenConverter;
//token令牌管理
@Bean
public AuthorizationServerTokenServices tokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setClientDetailsService(clientDetailsService); //客户端信息服务,即向哪个客户端颁发令牌
tokenServices.setSupportRefreshToken(true); //支持产生刷新令牌
tokenServices.setTokenStore(tokenStore); //令牌的存储策略
tokenServices.setAccessTokenValiditySeconds(7200); //令牌默认有效期2小时
tokenServices.setRefreshTokenValiditySeconds(259200); //refresh_token默认有效期三天
//令牌增强
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter));
tokenServices.setTokenEnhancer(tokenEnhancerChain);
return tokenServices;
}
/**
* token令牌端点访问的安全策略
* (不是所有人都可以来访问框架提供的这些令牌端点的)
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer authorizationServerSecurityConfigurer) throws Exception {
authorizationServerSecurityConfigurer.tokenKeyAccess("permitAll()") //oauth/token_key这个端点(url)是公开的,不用登录可调
.checkTokenAccess("permitAll()") // oauth/check_token这个端点是公开的
.allowFormAuthenticationForClients(); //允许客户端表单认证,申请令牌
}
/**
* Oauth2.0客户端角色的信息来源:内存、数据库
* 这里用数据库
*/
@Override
public void configure(ClientDetailsServiceConfigurer clientDetailsServiceConfigurer) throws Exception {
clientDetailsServiceConfigurer.withClientDetails(clientDetailsService);
}
/**
* 令牌端点访问和令牌服务(令牌怎么生成、怎么存储等)
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager) //设置认证管理器,密码模式需要
.authorizationCodeServices(authorizationCodeServices) //授权码模式需要
.approvalStore(approvalStore)
.tokenServices(tokenServices()) //token管理服务
.allowedTokenEndpointRequestMethods(HttpMethod.POST); //允许Post方式访问
}
}