diff --git a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java index 05bff8d71..c8366b35a 100644 --- a/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java +++ b/pigx-common/pigx-common-core/src/main/java/com/pig4cloud/pigx/common/core/constant/SecurityConstants.java @@ -178,33 +178,13 @@ public interface SecurityConstants { /** * 用户ID字段 */ - String DETAILS_USER_ID = "id"; + String DETAILS_USER_ID = "user_id"; /** * 用户名 */ String DETAILS_USERNAME = "username"; - /** - * 用户基本信息 - */ - String DETAILS_USER = "user_info"; - - /** - * 用户名phone - */ - String DETAILS_PHONE = "phone"; - - /** - * 头像 - */ - String DETAILS_AVATAR = "avatar"; - - /** - * 昵称 - */ - String NICKNAME = "nickname"; - /** * 姓名 */ diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxResourceServerConfigurerAdapter.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxResourceServerConfigurerAdapter.java index deb56e301..1555e8981 100644 --- a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxResourceServerConfigurerAdapter.java +++ b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxResourceServerConfigurerAdapter.java @@ -25,9 +25,7 @@ import org.springframework.security.config.annotation.web.configurers.Expression import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; import org.springframework.security.oauth2.provider.authentication.TokenExtractor; -import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter; import org.springframework.security.oauth2.provider.token.RemoteTokenServices; -import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter; import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.web.client.RestTemplate; @@ -73,12 +71,7 @@ public class PigxResourceServerConfigurerAdapter extends ResourceServerConfigure @Override public void configure(ResourceServerSecurityConfigurer resources) { - DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter(); - UserAuthenticationConverter userTokenConverter = new PigxUserAuthenticationConverter(); - accessTokenConverter.setUserTokenConverter(userTokenConverter); - remoteTokenServices.setRestTemplate(lbRestTemplate); - remoteTokenServices.setAccessTokenConverter(accessTokenConverter); resources.authenticationEntryPoint(resourceAuthExceptionEntryPoint).tokenExtractor(tokenExtractor) .tokenServices(remoteTokenServices); } diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxTokenEnhancer.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxTokenEnhancer.java index 251270826..269ddb9c5 100644 --- a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxTokenEnhancer.java +++ b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxTokenEnhancer.java @@ -18,6 +18,7 @@ package com.pig4cloud.pigx.common.security.component; import com.pig4cloud.pigx.common.core.constant.SecurityConstants; +import com.pig4cloud.pigx.common.security.service.PigxUser; import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.security.oauth2.provider.OAuth2Authentication; @@ -51,6 +52,15 @@ public class PigxTokenEnhancer implements TokenEnhancer { additionalInfo.put(SecurityConstants.DETAILS_LICENSE, SecurityConstants.PIGX_LICENSE); additionalInfo.put(SecurityConstants.ACTIVE, Boolean.TRUE); + // 客户端模式不返回具体用户信息 + if (SecurityConstants.CLIENT_CREDENTIALS.equals(authentication.getOAuth2Request().getGrantType())) { + ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo); + return accessToken; + } + + PigxUser pigxUser = (PigxUser) authentication.getUserAuthentication().getPrincipal(); + additionalInfo.put(SecurityConstants.DETAILS_USER_ID, pigxUser.getId()); + additionalInfo.put(SecurityConstants.DETAILS_USERNAME, pigxUser.getUsername()); ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo); return accessToken; } diff --git a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxUserAuthenticationConverter.java b/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxUserAuthenticationConverter.java deleted file mode 100644 index bb4a1de38..000000000 --- a/pigx-common/pigx-common-security/src/main/java/com/pig4cloud/pigx/common/security/component/PigxUserAuthenticationConverter.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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 (wangiegie@gmail.com) - */ - -package com.pig4cloud.pigx.common.security.component; - -import cn.hutool.core.map.MapUtil; -import cn.hutool.core.util.StrUtil; -import com.pig4cloud.pigx.common.core.constant.CommonConstants; -import com.pig4cloud.pigx.common.core.constant.SecurityConstants; -import com.pig4cloud.pigx.common.security.exception.PigxAuth2Exception; -import com.pig4cloud.pigx.common.security.service.PigxUser; -import com.pig4cloud.pigx.common.security.util.PigxSecurityMessageSourceUtil; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.AuthorityUtils; -import org.springframework.security.oauth2.provider.token.UserAuthenticationConverter; -import org.springframework.util.StringUtils; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; - -import javax.servlet.http.HttpServletRequest; -import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Optional; - -/** - * @author lengleng - * @date 2019-03-07 - *

- * 根据checktoken 的结果转化用户信息 - *

- * 问题分析: 认证服务器check-token 返回的全部信息 资源服务器在根据返回信息组装用户信息的时候,只是用了username 如果设置了 - * userDetailsService 的实现则去调用 loadUserByUsername 再去查询一次用户信息 - *

- * 造成问题现象 如果设置了userDetailsService 即可在spring security 上下文获取用户的全部信息,不设置则只能得到用户名。 - * 增加了一次查询逻辑,对性能产生不必要的影响 - *

- * 解决问题 扩展UserAuthenticationConverter 的解析过程,把认证服务器返回的信息全部组装到spring security的上下文对象中 - */ -@Slf4j -public class PigxUserAuthenticationConverter implements UserAuthenticationConverter { - - private static final String N_A = "N/A"; - - /** - * Extract information about the user to be used in an access token (i.e. for resource - * servers). - * @param authentication an authentication representing a user - * @return a map of key values representing the unique information about the user - */ - @Override - public Map convertUserAuthentication(Authentication authentication) { - Map response = new LinkedHashMap<>(); - response.put(USERNAME, authentication.getName()); - if (authentication.getAuthorities() != null && !authentication.getAuthorities().isEmpty()) { - response.put(AUTHORITIES, AuthorityUtils.authorityListToSet(authentication.getAuthorities())); - } - return response; - } - - /** - * Inverse of {@link #convertUserAuthentication(Authentication)}. Extracts an - * Authentication from a map. - * @param responseMap a map of user information - * @return an Authentication representing the user or null if there is none - */ - @Override - public Authentication extractAuthentication(Map responseMap) { - if (responseMap.containsKey(USERNAME)) { - Collection authorities = getAuthorities(responseMap); - Map map = MapUtil.get(responseMap, SecurityConstants.DETAILS_USER, Map.class); - validateTenantId(map); - String name = MapUtil.getStr(map, SecurityConstants.NAME); - String email = MapUtil.getStr(map, SecurityConstants.EMAIL); - String nickname = MapUtil.getStr(map, SecurityConstants.NICKNAME); - String username = MapUtil.getStr(map, SecurityConstants.DETAILS_USERNAME); - Long id = MapUtil.getLong(map, SecurityConstants.DETAILS_USER_ID); - Long deptId = MapUtil.getLong(map, SecurityConstants.DETAILS_DEPT_ID); - Long tenantId = MapUtil.getLong(map, SecurityConstants.DETAILS_TENANT_ID); - String phone = MapUtil.getStr(map, SecurityConstants.DETAILS_PHONE); - String avatar = MapUtil.getStr(map, SecurityConstants.DETAILS_AVATAR); - PigxUser user = new PigxUser(id, username, deptId, phone, avatar, nickname, name, email, tenantId, N_A, - true, true, true, true, authorities); - return new UsernamePasswordAuthenticationToken(user, N_A, authorities); - } - return null; - } - - private Collection getAuthorities(Map map) { - Object authorities = map.get(AUTHORITIES); - if (authorities instanceof String) { - return AuthorityUtils.commaSeparatedStringToAuthorityList((String) authorities); - } - if (authorities instanceof Collection) { - return AuthorityUtils.commaSeparatedStringToAuthorityList( - StringUtils.collectionToCommaDelimitedString((Collection) authorities)); - } - return AuthorityUtils.NO_AUTHORITIES; - } - - private void validateTenantId(Map map) { - String headerValue = getCurrentTenantId(); - Integer userValue = MapUtil.getInt(map, SecurityConstants.DETAILS_TENANT_ID); - if (StrUtil.isNotBlank(headerValue) && !userValue.toString().equals(headerValue)) { - log.warn("请求头中的租户ID({})和用户的租户ID({})不一致", headerValue, userValue); - // TODO: 不要提示租户ID不对,可能被穷举 - throw new PigxAuth2Exception(PigxSecurityMessageSourceUtil.getAccessor().getMessage( - "AbstractUserDetailsAuthenticationProvider.badTenantId", new Object[] { headerValue }, - "Bad tenant ID")); - } - } - - private Optional getCurrentHttpRequest() { - return Optional.ofNullable(RequestContextHolder.getRequestAttributes()).filter( - requestAttributes -> ServletRequestAttributes.class.isAssignableFrom(requestAttributes.getClass())) - .map(requestAttributes -> ((ServletRequestAttributes) requestAttributes)) - .map(ServletRequestAttributes::getRequest); - } - - private String getCurrentTenantId() { - return getCurrentHttpRequest() - .map(httpServletRequest -> httpServletRequest.getHeader(CommonConstants.TENANT_ID)).orElse(null); - } - -}