/* * Copyright (c) 2018-2025, lengleng All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the pig4cloud.com developer nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * Author: lengleng ([email protected]) */ package com.github.pig.auth.config; import com.github.pig.auth.util.UserDetailsImpl; import com.github.pig.common.constant.CommonConstant; import com.github.pig.common.constant.SecurityConstants; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; 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.TokenStore; import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore; import javax.sql.DataSource; import java.util.Arrays; import java.util.HashMap; import java.util.Map; /** * @author lengleng * @date 2017/10/27 * 认证服务器逻辑实现 */ @Configuration @Order(Integer.MIN_VALUE) @EnableAuthorizationServer public class PigAuthorizationConfig extends AuthorizationServerConfigurerAdapter { @Autowired private DataSource dataSource; @Autowired private AuthenticationManager authenticationManager; @Autowired private UserDetailsService userDetailsService; @Autowired private RedisConnectionFactory redisConnectionFactory; @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { JdbcClientDetailsService clientDetailsService = new JdbcClientDetailsService(dataSource); clientDetailsService.setSelectClientDetailsSql(SecurityConstants.DEFAULT_SELECT_STATEMENT); clientDetailsService.setFindClientDetailsSql(SecurityConstants.DEFAULT_FIND_STATEMENT); clients.withClientDetails(clientDetailsService); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) { //token增强配置 TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain(); tokenEnhancerChain.setTokenEnhancers( Arrays.asList(tokenEnhancer(), jwtAccessTokenConverter())); endpoints .tokenStore(redisTokenStore()) .tokenEnhancer(tokenEnhancerChain) .authenticationManager(authenticationManager) .reuseRefreshTokens(false) .userDetailsService(userDetailsService); } @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security .allowFormAuthenticationForClients() .tokenKeyAccess("isAuthenticated()") .checkTokenAccess("permitAll()"); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public JwtAccessTokenConverter jwtAccessTokenConverter() { PigJwtAccessTokenConverter jwtAccessTokenConverter = new PigJwtAccessTokenConverter(); jwtAccessTokenConverter.setSigningKey(CommonConstant.SIGN_KEY); return jwtAccessTokenConverter; } /** * tokenstore 定制化处理 * * @return TokenStore * 1. 如果使用的 redis-cluster 模式请使用 PigRedisTokenStore * PigRedisTokenStore tokenStore = new PigRedisTokenStore(); * tokenStore.setRedisTemplate(redisTemplate); */ @Bean public TokenStore redisTokenStore() { RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory); tokenStore.setPrefix(SecurityConstants.PIG_PREFIX); return tokenStore; } /** * jwt 生成token 定制化处理 * * @return TokenEnhancer */ @Bean public TokenEnhancer tokenEnhancer() { return (accessToken, authentication) -> { final Map<String, Object> additionalInfo = new HashMap<>(2); additionalInfo.put("license", SecurityConstants.PIG_LICENSE); UserDetailsImpl user = (UserDetailsImpl) authentication.getUserAuthentication().getPrincipal(); if (user != null) { additionalInfo.put("userId", user.getUserId()); } ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo); return accessToken; }; } }