content: package jnpf.config;
  
  import cn.hutool.http.HttpStatus;
  import cn.hutool.json.JSONUtil;
  import jnpf.config.jwt.JwtTokenEnhancer;
  import jnpf.impl.JdbcClientDetailsServiceImpl;
  import jnpf.impl.UserDetailsServiceImpl;
  import jnpf.base.ActionResult;
  import org.springframework.beans.factory.annotation.Autowired;
  import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;
  import org.springframework.core.io.ClassPathResource;
  import org.springframework.http.HttpHeaders;
  import org.springframework.http.MediaType;
  import org.springframework.security.authentication.AuthenticationManager;
  import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
  import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
  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.client.JdbcClientDetailsService;
  import org.springframework.security.oauth2.provider.token.TokenEnhancer;
  import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
  import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
  import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
  import org.springframework.security.web.AuthenticationEntryPoint;
  
  import javax.sql.DataSource;
  import java.security.KeyPair;
  import java.util.ArrayList;
  import java.util.List;
  
  /**
   * 客户端认证
   *
   * @author JNPF开发平台组
   * @version V3.1.0
   * @copyright 引迈信息技术有限公司（https://www.jnpfsoft.com）
   * @date 2021-03-23
   */
  @EnableAuthorizationServer
  @Configuration
  public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
      @Autowired
      private UserDetailsServiceImpl userDetailsService;
      @Autowired
      private JwtTokenEnhancer jwtTokenEnhancer;
      @Autowired
      private AuthenticationManager authenticationManager;
      @Autowired
      private DataSource dataSource;
  
      /**
       * 配置允许的客户端
       * @param clients
       * @throws Exception
       */
      @Override
      public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
          JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsServiceImpl(dataSource);
          clients.withClientDetails(jdbcClientDetailsService);
      }
  
      /**
       * 允许表单验证
       * @param security
       * @throws Exception
       */
      @Override
      public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
          security.allowFormAuthenticationForClients();
      }
  
  
      /**
       * 自定义认证异常响应数据
       * @return
       */
      @Bean
      public AuthenticationEntryPoint authenticationEntryPoint() {
          return (request, response, e) -> {
              response.setStatus(HttpStatus.HTTP_OK);
              response.setHeader(HttpHeaders.CONTENT_TYPE, "application/json;charset=UTF-8");
              response.setHeader("Access-Control-Allow-Origin", "*");
              response.setHeader("Cache-Control", "no-cache");
              ActionResult result = ActionResult.fail("客户端认证失败");
              response.getWriter().print(JSONUtil.toJsonStr(result));
              response.getWriter().flush();
          };
      }
  
  
      @Override
      public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
          TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
          List<TokenEnhancer> tokenEnhancer = new ArrayList<>();
          //配置Jwt内容填充器
          tokenEnhancer.add(jwtTokenEnhancer);
          tokenEnhancer.add(jwtAccessTokenConverter());
          tokenEnhancerChain.setTokenEnhancers(tokenEnhancer);
          endpoints.authenticationManager(authenticationManager)
                  .userDetailsService(userDetailsService)
                  .accessTokenConverter(jwtAccessTokenConverter())
                  .tokenEnhancer(tokenEnhancerChain)
                  .pathMapping("/oauth/token","/Login")
                  //不可重复使用
                  .reuseRefreshTokens(false);
      }
  
      /**
       * 加密jwt
       * @return
       */
      @Bean
      public JwtAccessTokenConverter jwtAccessTokenConverter(){
          JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
          jwtAccessTokenConverter.setKeyPair(keyPair());
          return jwtAccessTokenConverter;
      }
  
      /**
       * 读取resource下的jwt.jks文件
       * @return
       */
      @Bean
      public KeyPair keyPair(){
          KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("jnpf.jks"),"123456".toCharArray());
          return keyStoreKeyFactory.getKeyPair("jnpf","123456".toCharArray());
      }
  
  }
  