💚 Fixing CI Build. 格式化代码

This commit is contained in:
lbw 2021-07-04 14:34:05 +08:00
parent eaa3458e0c
commit 9caa82e34e
21 changed files with 1360 additions and 1353 deletions

View File

@ -19,12 +19,10 @@ package com.pig4cloud.pig.auth.endpoint;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pig4cloud.pig.auth.handler.PigLogoutSuccessEventHandler;
import com.pig4cloud.pig.common.core.constant.CacheConstants;
import com.pig4cloud.pig.common.core.constant.CommonConstants;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.core.util.SpringContextHolder;
import com.pig4cloud.pig.common.log.event.SysLogEvent;
import com.pig4cloud.pig.common.security.annotation.Inner;
import com.pig4cloud.pig.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
@ -38,7 +36,6 @@ import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.authentication.event.LogoutSuccessEvent;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
@ -148,7 +145,7 @@ public class PigTokenEndpoint {
OAuth2RefreshToken refreshToken = accessToken.getRefreshToken();
tokenStore.removeRefreshToken(refreshToken);
//处理自定义退出事件保存相关日志
// 处理自定义退出事件保存相关日志
SpringContextHolder.publishEvent(new LogoutSuccessEvent(auth2Authentication));
return R.ok();
}

View File

@ -39,7 +39,6 @@ public class PigLogoutSuccessEventHandler extends AbstractLogoutSuccessEventHand
* 处理退出成功方法
* <p>
* 获取到登录的authentication 对象
*
* @param authentication 登录对象
*/
@Override

View File

@ -69,13 +69,14 @@ public class SysLogUtils {
OAuth2Authentication auth2Authentication = (OAuth2Authentication) authentication;
return auth2Authentication.getOAuth2Request().getClientId();
}
if (authentication instanceof UsernamePasswordAuthenticationToken){
if (authentication instanceof UsernamePasswordAuthenticationToken) {
// 通过请求参数拿到clientId
String authorizationHeaderValue = request.getHeader("Authorization");
String base64AuthorizationHeader = Optional.ofNullable(authorizationHeaderValue)
.map(headerValue->headerValue.substring("Basic ".length())).orElse("");
if(StrUtil.isNotEmpty(base64AuthorizationHeader)) {
String decodedAuthorizationHeader = new String(Base64.getDecoder().decode(base64AuthorizationHeader), Charset.forName("UTF-8"));
.map(headerValue -> headerValue.substring("Basic ".length())).orElse("");
if (StrUtil.isNotEmpty(base64AuthorizationHeader)) {
String decodedAuthorizationHeader = new String(Base64.getDecoder().decode(base64AuthorizationHeader),
Charset.forName("UTF-8"));
return decodedAuthorizationHeader.split(":")[0];
}
}

View File

@ -26,8 +26,7 @@ import org.springframework.security.core.Authentication;
* @author zhangran
* @date 2021/6/23 退出成功事件处理器
*/
public abstract class AbstractLogoutSuccessEventHandler
implements ApplicationListener<LogoutSuccessEvent> {
public abstract class AbstractLogoutSuccessEventHandler implements ApplicationListener<LogoutSuccessEvent> {
/**
* Handle an application event.

View File

@ -42,37 +42,37 @@ import org.springframework.web.filter.CorsFilter;
@EnableScheduling
@PropertySource("/application.properties")
public class ConsoleConfig {
@Autowired
private ControllerMethodsCache methodsCache;
/**
* Init.
*/
@PostConstruct
public void init() {
methodsCache.initClassMethod("com.alibaba.nacos.core.controller");
methodsCache.initClassMethod("com.alibaba.nacos.naming.controllers");
methodsCache.initClassMethod("com.alibaba.nacos.config.server.controller");
methodsCache.initClassMethod("com.alibaba.nacos.controller");
}
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.setMaxAge(18000L);
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(ZoneId.systemDefault().toString());
}
@Autowired
private ControllerMethodsCache methodsCache;
/**
* Init.
*/
@PostConstruct
public void init() {
methodsCache.initClassMethod("com.alibaba.nacos.core.controller");
methodsCache.initClassMethod("com.alibaba.nacos.naming.controllers");
methodsCache.initClassMethod("com.alibaba.nacos.config.server.controller");
methodsCache.initClassMethod("com.alibaba.nacos.controller");
}
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.setMaxAge(18000L);
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
@Bean
public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization() {
return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(ZoneId.systemDefault().toString());
}
}

View File

@ -37,74 +37,77 @@ import javax.servlet.http.HttpServletRequest;
@RestController("consoleHealth")
@RequestMapping("/v1/console/health")
public class HealthController {
private static final Logger LOGGER = LoggerFactory.getLogger(HealthController.class);
private final PersistService persistService;
private final OperatorController apiCommands;
@Autowired
public HealthController(PersistService persistService, OperatorController apiCommands) {
this.persistService = persistService;
this.apiCommands = apiCommands;
}
/**
* Whether the Nacos is in broken states or not, and cannot recover except by being restarted.
*
* @return HTTP code equal to 200 indicates that Nacos is in right states. HTTP code equal to 500 indicates that
* Nacos is in broken states.
*/
@GetMapping("/liveness")
public ResponseEntity<String> liveness() {
return ResponseEntity.ok().body("OK");
}
/**
* Ready to receive the request or not.
*
* @return HTTP code equal to 200 indicates that Nacos is ready. HTTP code equal to 500 indicates that Nacos is not
* ready.
*/
@GetMapping("/readiness")
public ResponseEntity<String> readiness(HttpServletRequest request) {
boolean isConfigReadiness = isConfigReadiness();
boolean isNamingReadiness = isNamingReadiness(request);
if (isConfigReadiness && isNamingReadiness) {
return ResponseEntity.ok().body("OK");
}
if (!isConfigReadiness && !isNamingReadiness) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Config and Naming are not in readiness");
}
if (!isConfigReadiness) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Config is not in readiness");
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Naming is not in readiness");
}
private boolean isConfigReadiness() {
// check db
try {
persistService.configInfoCount("");
return true;
} catch (Exception e) {
LOGGER.error("Config health check fail.", e);
}
return false;
}
private boolean isNamingReadiness(HttpServletRequest request) {
try {
apiCommands.metrics(request);
return true;
} catch (Exception e) {
LOGGER.error("Naming health check fail.", e);
}
return false;
}
private static final Logger LOGGER = LoggerFactory.getLogger(HealthController.class);
private final PersistService persistService;
private final OperatorController apiCommands;
@Autowired
public HealthController(PersistService persistService, OperatorController apiCommands) {
this.persistService = persistService;
this.apiCommands = apiCommands;
}
/**
* Whether the Nacos is in broken states or not, and cannot recover except by being
* restarted.
* @return HTTP code equal to 200 indicates that Nacos is in right states. HTTP code
* equal to 500 indicates that Nacos is in broken states.
*/
@GetMapping("/liveness")
public ResponseEntity<String> liveness() {
return ResponseEntity.ok().body("OK");
}
/**
* Ready to receive the request or not.
* @return HTTP code equal to 200 indicates that Nacos is ready. HTTP code equal to
* 500 indicates that Nacos is not ready.
*/
@GetMapping("/readiness")
public ResponseEntity<String> readiness(HttpServletRequest request) {
boolean isConfigReadiness = isConfigReadiness();
boolean isNamingReadiness = isNamingReadiness(request);
if (isConfigReadiness && isNamingReadiness) {
return ResponseEntity.ok().body("OK");
}
if (!isConfigReadiness && !isNamingReadiness) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Config and Naming are not in readiness");
}
if (!isConfigReadiness) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Config is not in readiness");
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Naming is not in readiness");
}
private boolean isConfigReadiness() {
// check db
try {
persistService.configInfoCount("");
return true;
}
catch (Exception e) {
LOGGER.error("Config health check fail.", e);
}
return false;
}
private boolean isNamingReadiness(HttpServletRequest request) {
try {
apiCommands.metrics(request);
return true;
}
catch (Exception e) {
LOGGER.error("Naming health check fail.", e);
}
return false;
}
}

View File

@ -69,8 +69,7 @@ public class NamespaceController {
/**
* Get namespace list.
*
* @param request request
* @param request request
* @param response response
* @return namespace list
*/
@ -78,8 +77,8 @@ public class NamespaceController {
public RestResult<List<Namespace>> getNamespaces(HttpServletRequest request, HttpServletResponse response) {
// TODO 获取用kp
List<TenantInfo> tenantInfos = persistService.findTenantByKp(DEFAULT_KP);
Namespace namespace0 = new Namespace("", DEFAULT_NAMESPACE, DEFAULT_QUOTA, persistService.configInfoCount(DEFAULT_TENANT),
NamespaceTypeEnum.GLOBAL.getType());
Namespace namespace0 = new Namespace("", DEFAULT_NAMESPACE, DEFAULT_QUOTA,
persistService.configInfoCount(DEFAULT_TENANT), NamespaceTypeEnum.GLOBAL.getType());
List<Namespace> namespaces = new ArrayList<Namespace>();
namespaces.add(namespace0);
for (TenantInfo tenantInfo : tenantInfos) {
@ -93,32 +92,32 @@ public class NamespaceController {
/**
* get namespace all info by namespace id.
*
* @param request request
* @param response response
* @param request request
* @param response response
* @param namespaceId namespaceId
* @return namespace all info
*/
@GetMapping(params = "show=all")
public NamespaceAllInfo getNamespace(HttpServletRequest request, HttpServletResponse response,
@RequestParam("namespaceId") String namespaceId) {
@RequestParam("namespaceId") String namespaceId) {
// TODO 获取用kp
if (StringUtils.isBlank(namespaceId)) {
return new NamespaceAllInfo(namespaceId, DEFAULT_NAMESPACE_SHOW_NAME, DEFAULT_QUOTA, persistService.configInfoCount(DEFAULT_TENANT),
NamespaceTypeEnum.GLOBAL.getType(), DEFAULT_NAMESPACE_DESCRIPTION);
} else {
return new NamespaceAllInfo(namespaceId, DEFAULT_NAMESPACE_SHOW_NAME, DEFAULT_QUOTA,
persistService.configInfoCount(DEFAULT_TENANT), NamespaceTypeEnum.GLOBAL.getType(),
DEFAULT_NAMESPACE_DESCRIPTION);
}
else {
TenantInfo tenantInfo = persistService.findTenantByKp(DEFAULT_KP, namespaceId);
int configCount = persistService.configInfoCount(namespaceId);
return new NamespaceAllInfo(namespaceId, tenantInfo.getTenantName(), DEFAULT_QUOTA, configCount, NamespaceTypeEnum.CUSTOM.getType(),
tenantInfo.getTenantDesc());
return new NamespaceAllInfo(namespaceId, tenantInfo.getTenantName(), DEFAULT_QUOTA, configCount,
NamespaceTypeEnum.CUSTOM.getType(), tenantInfo.getTenantDesc());
}
}
/**
* create namespace.
*
* @param request request
* @param response response
* @param request request
* @param response response
* @param namespaceName namespace Name
* @param namespaceDesc namespace Desc
* @return whether create ok
@ -126,12 +125,13 @@ public class NamespaceController {
@PostMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "namespaces", action = ActionTypes.WRITE)
public Boolean createNamespace(HttpServletRequest request, HttpServletResponse response,
@RequestParam("customNamespaceId") String namespaceId, @RequestParam("namespaceName") String namespaceName,
@RequestParam(value = "namespaceDesc", required = false) String namespaceDesc) {
@RequestParam("customNamespaceId") String namespaceId, @RequestParam("namespaceName") String namespaceName,
@RequestParam(value = "namespaceDesc", required = false) String namespaceDesc) {
// TODO 获取用kp
if (StringUtils.isBlank(namespaceId)) {
namespaceId = UUID.randomUUID().toString();
} else {
}
else {
namespaceId = namespaceId.trim();
if (!namespaceIdCheckPattern.matcher(namespaceId).matches()) {
return false;
@ -143,14 +143,13 @@ public class NamespaceController {
return false;
}
}
persistService.insertTenantInfoAtomic(DEFAULT_KP, namespaceId, namespaceName, namespaceDesc, DEFAULT_CREATE_SOURCE,
System.currentTimeMillis());
persistService.insertTenantInfoAtomic(DEFAULT_KP, namespaceId, namespaceName, namespaceDesc,
DEFAULT_CREATE_SOURCE, System.currentTimeMillis());
return true;
}
/**
* check namespaceId exist.
*
* @param namespaceId namespace id
* @return true if exist, otherwise false
*/
@ -164,17 +163,16 @@ public class NamespaceController {
/**
* edit namespace.
*
* @param namespace namespace
* @param namespace namespace
* @param namespaceShowName namespace ShowName
* @param namespaceDesc namespace Desc
* @param namespaceDesc namespace Desc
* @return whether edit ok
*/
@PutMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "namespaces", action = ActionTypes.WRITE)
public Boolean editNamespace(@RequestParam("namespace") String namespace,
@RequestParam("namespaceShowName") String namespaceShowName,
@RequestParam(value = "namespaceDesc", required = false) String namespaceDesc) {
@RequestParam("namespaceShowName") String namespaceShowName,
@RequestParam(value = "namespaceDesc", required = false) String namespaceDesc) {
// TODO 获取用kp
persistService.updateTenantNameAtomic(DEFAULT_KP, namespace, namespaceShowName, namespaceDesc);
return true;
@ -182,16 +180,15 @@ public class NamespaceController {
/**
* del namespace by id.
*
* @param request request
* @param response response
* @param request request
* @param response response
* @param namespaceId namespace Id
* @return whether del ok
*/
@DeleteMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "namespaces", action = ActionTypes.WRITE)
public Boolean deleteConfig(HttpServletRequest request, HttpServletResponse response,
@RequestParam("namespaceId") String namespaceId) {
@RequestParam("namespaceId") String namespaceId) {
persistService.removeTenantInfoAtomic(DEFAULT_KP, namespaceId);
return true;
}

View File

@ -39,53 +39,51 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/v1/auth/permissions")
public class PermissionController {
@Autowired
private NacosRoleServiceImpl nacosRoleService;
/**
* Query permissions of a role.
*
* @param role the role
* @param pageNo page index
* @param pageSize page size
* @return permission of a role
*/
@GetMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "permissions", action = ActionTypes.READ)
public Object getPermissions(@RequestParam int pageNo, @RequestParam int pageSize,
@RequestParam(name = "role", defaultValue = StringUtils.EMPTY) String role) {
return nacosRoleService.getPermissionsFromDatabase(role, pageNo, pageSize);
}
/**
* Add a permission to a role.
*
* @param role the role
* @param resource the related resource
* @param action the related action
* @return ok if succeed
*/
@PostMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "permissions", action = ActionTypes.WRITE)
public Object addPermission(@RequestParam String role, @RequestParam String resource, @RequestParam String action) {
nacosRoleService.addPermission(role, resource, action);
return RestResultUtils.success("add permission ok!");
}
/**
* Delete a permission from a role.
*
* @param role the role
* @param resource the related resource
* @param action the related action
* @return ok if succeed
*/
@DeleteMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "permissions", action = ActionTypes.WRITE)
public Object deletePermission(@RequestParam String role, @RequestParam String resource,
@RequestParam String action) {
nacosRoleService.deletePermission(role, resource, action);
return RestResultUtils.success("delete permission ok!");
}
@Autowired
private NacosRoleServiceImpl nacosRoleService;
/**
* Query permissions of a role.
* @param role the role
* @param pageNo page index
* @param pageSize page size
* @return permission of a role
*/
@GetMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "permissions", action = ActionTypes.READ)
public Object getPermissions(@RequestParam int pageNo, @RequestParam int pageSize,
@RequestParam(name = "role", defaultValue = StringUtils.EMPTY) String role) {
return nacosRoleService.getPermissionsFromDatabase(role, pageNo, pageSize);
}
/**
* Add a permission to a role.
* @param role the role
* @param resource the related resource
* @param action the related action
* @return ok if succeed
*/
@PostMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "permissions", action = ActionTypes.WRITE)
public Object addPermission(@RequestParam String role, @RequestParam String resource, @RequestParam String action) {
nacosRoleService.addPermission(role, resource, action);
return RestResultUtils.success("add permission ok!");
}
/**
* Delete a permission from a role.
* @param role the role
* @param resource the related resource
* @param action the related action
* @return ok if succeed
*/
@DeleteMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "permissions", action = ActionTypes.WRITE)
public Object deletePermission(@RequestParam String role, @RequestParam String resource,
@RequestParam String action) {
nacosRoleService.deletePermission(role, resource, action);
return RestResultUtils.success("delete permission ok!");
}
}

View File

@ -41,70 +41,69 @@ import java.util.List;
@RestController
@RequestMapping("/v1/auth/roles")
public class RoleController {
@Autowired
private NacosRoleServiceImpl roleService;
/**
* Get roles list.
*
* @param pageNo number index of page
* @param pageSize page size
* @param username optional, username of user
* @return role list
*/
@GetMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "roles", action = ActionTypes.READ)
public Object getRoles(@RequestParam int pageNo, @RequestParam int pageSize,
@RequestParam(name = "username", defaultValue = "") String username) {
return roleService.getRolesFromDatabase(username, pageNo, pageSize);
}
/**
* Fuzzy matching role name .
*
* @param role role id
* @return role list
*/
@GetMapping("/search")
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "roles", action = ActionTypes.READ)
public List<String> searchRoles(@RequestParam String role) {
return roleService.findRolesLikeRoleName(role);
}
/**
* Add a role to a user
*
* <p>This method is used for 2 functions: 1. create a role and bind it to GLOBAL_ADMIN. 2. bind a role to an user.
*
* @param role role name
* @param username username
* @return Code 200 and message 'add role ok!'
*/
@PostMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "roles", action = ActionTypes.WRITE)
public Object addRole(@RequestParam String role, @RequestParam String username) {
roleService.addRole(role, username);
return RestResultUtils.success("add role ok!");
}
/**
* Delete a role. If no username is specified, all users under this role are deleted.
*
* @param role role
* @param username username
* @return ok if succeed
*/
@DeleteMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "roles", action = ActionTypes.WRITE)
public Object deleteRole(@RequestParam String role,
@RequestParam(name = "username", defaultValue = StringUtils.EMPTY) String username) {
if (StringUtils.isBlank(username)) {
roleService.deleteRole(role);
} else {
roleService.deleteRole(role, username);
}
return RestResultUtils.success("delete role of user " + username + " ok!");
}
@Autowired
private NacosRoleServiceImpl roleService;
/**
* Get roles list.
* @param pageNo number index of page
* @param pageSize page size
* @param username optional, username of user
* @return role list
*/
@GetMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "roles", action = ActionTypes.READ)
public Object getRoles(@RequestParam int pageNo, @RequestParam int pageSize,
@RequestParam(name = "username", defaultValue = "") String username) {
return roleService.getRolesFromDatabase(username, pageNo, pageSize);
}
/**
* Fuzzy matching role name .
* @param role role id
* @return role list
*/
@GetMapping("/search")
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "roles", action = ActionTypes.READ)
public List<String> searchRoles(@RequestParam String role) {
return roleService.findRolesLikeRoleName(role);
}
/**
* Add a role to a user
*
* <p>
* This method is used for 2 functions: 1. create a role and bind it to GLOBAL_ADMIN.
* 2. bind a role to an user.
* @param role role name
* @param username username
* @return Code 200 and message 'add role ok!'
*/
@PostMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "roles", action = ActionTypes.WRITE)
public Object addRole(@RequestParam String role, @RequestParam String username) {
roleService.addRole(role, username);
return RestResultUtils.success("add role ok!");
}
/**
* Delete a role. If no username is specified, all users under this role are deleted.
* @param role role
* @param username username
* @return ok if succeed
*/
@DeleteMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "roles", action = ActionTypes.WRITE)
public Object deleteRole(@RequestParam String role,
@RequestParam(name = "username", defaultValue = StringUtils.EMPTY) String username) {
if (StringUtils.isBlank(username)) {
roleService.deleteRole(role);
}
else {
roleService.deleteRole(role, username);
}
return RestResultUtils.success("delete role of user " + username + " ok!");
}
}

View File

@ -34,22 +34,21 @@ import java.util.Map;
@RestController
@RequestMapping("/v1/console/server")
public class ServerStateController {
/**
* Get server state of current server.
*
* @return state json.
*/
@GetMapping("/state")
public ResponseEntity<Map<String, String>> serverState() {
Map<String, String> serverState = new HashMap<>(4);
serverState.put("standalone_mode",
EnvUtil.getStandaloneMode() ? EnvUtil.STANDALONE_MODE_ALONE : EnvUtil.STANDALONE_MODE_CLUSTER);
serverState.put("function_mode", EnvUtil.getFunctionMode());
serverState.put("version", VersionUtils.version);
return ResponseEntity.ok().body(serverState);
}
/**
* Get server state of current server.
* @return state json.
*/
@GetMapping("/state")
public ResponseEntity<Map<String, String>> serverState() {
Map<String, String> serverState = new HashMap<>(4);
serverState.put("standalone_mode",
EnvUtil.getStandaloneMode() ? EnvUtil.STANDALONE_MODE_ALONE : EnvUtil.STANDALONE_MODE_CLUSTER);
serverState.put("function_mode", EnvUtil.getFunctionMode());
serverState.put("version", VersionUtils.version);
return ResponseEntity.ok().body(serverState);
}
}

View File

@ -65,218 +65,217 @@ import java.util.List;
* @author nkorange
*/
@RestController("user")
@RequestMapping({"/v1/auth", "/v1/auth/users"})
@RequestMapping({ "/v1/auth", "/v1/auth/users" })
public class UserController {
@Autowired
private JwtTokenManager jwtTokenManager;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private NacosUserDetailsServiceImpl userDetailsService;
@Autowired
private NacosRoleServiceImpl roleService;
@Autowired
private AuthConfigs authConfigs;
@Autowired
private NacosAuthManager authManager;
/**
* Create a new user.
*
* @param username username
* @param password password
* @return ok if create succeed
* @throws IllegalArgumentException if user already exist
* @since 1.2.0
*/
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE)
@PostMapping
public Object createUser(@RequestParam String username, @RequestParam String password) {
User user = userDetailsService.getUserFromDatabase(username);
if (user != null) {
throw new IllegalArgumentException("user '" + username + "' already exist!");
}
userDetailsService.createUser(username, PasswordEncoderUtil.encode(password));
return RestResultUtils.success("create user ok!");
}
/**
* Delete an existed user.
*
* @param username username of user
* @return ok if deleted succeed, keep silent if user not exist
* @since 1.2.0
*/
@DeleteMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE)
public Object deleteUser(@RequestParam String username) {
List<RoleInfo> roleInfoList = roleService.getRoles(username);
if (roleInfoList != null) {
for (RoleInfo roleInfo : roleInfoList) {
if (roleInfo.getRole().equals(NacosRoleServiceImpl.GLOBAL_ADMIN_ROLE)) {
throw new IllegalArgumentException("cannot delete admin: " + username);
}
}
}
userDetailsService.deleteUser(username);
return RestResultUtils.success("delete user ok!");
}
/**
* Update an user.
*
* @param username username of user
* @param newPassword new password of user
* @param response http response
* @param request http request
* @return ok if update succeed
* @throws IllegalArgumentException if user not exist or oldPassword is incorrect
* @since 1.2.0
*/
@PutMapping
@Secured(resource = NacosAuthConfig.UPDATE_PASSWORD_ENTRY_POINT, action = ActionTypes.WRITE)
public Object updateUser(@RequestParam String username, @RequestParam String newPassword,
HttpServletResponse response, HttpServletRequest request) throws IOException {
// admin or same user
if (!hasPermission(username, request)) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "authorization failed!");
}
User user = userDetailsService.getUserFromDatabase(username);
if (user == null) {
throw new IllegalArgumentException("user " + username + " not exist!");
}
userDetailsService.updateUserPassword(username, PasswordEncoderUtil.encode(newPassword));
return RestResultUtils.success("update user ok!");
}
@Autowired
private JwtTokenManager jwtTokenManager;
private boolean hasPermission(String username, HttpServletRequest request) {
if (!authConfigs.isAuthEnabled()) {
return true;
}
if (Objects.isNull(request.getAttribute(RequestUtil.NACOS_USER_KEY))) {
return false;
}
@Autowired
private AuthenticationManager authenticationManager;
NacosUser user = (NacosUser) request.getAttribute(RequestUtil.NACOS_USER_KEY);
// admin
if (user.isGlobalAdmin()) {
return true;
}
// same user
return user.getUserName().equals(username);
}
/**
* Get paged users.
*
* @param pageNo number index of page
* @param pageSize size of page
* @return A collection of users, empty set if no user is found
* @since 1.2.0
*/
@GetMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.READ)
public Object getUsers(@RequestParam int pageNo, @RequestParam int pageSize) {
return userDetailsService.getUsersFromDatabase(pageNo, pageSize);
}
/**
* Login to Nacos
*
* <p>This methods uses username and password to require a new token.
*
* @param username username of user
* @param password password
* @param response http response
* @param request http request
* @return new token of the user
* @throws AccessException if user info is incorrect
*/
@PostMapping("/login")
public Object login(@RequestParam String username, @RequestParam String password, HttpServletResponse response,
HttpServletRequest request) throws AccessException {
if (AuthSystemTypes.NACOS.name().equalsIgnoreCase(authConfigs.getNacosAuthSystemType()) || AuthSystemTypes.LDAP
.name().equalsIgnoreCase(authConfigs.getNacosAuthSystemType())) {
NacosUser user = (NacosUser) authManager.login(request);
response.addHeader(NacosAuthConfig.AUTHORIZATION_HEADER, NacosAuthConfig.TOKEN_PREFIX + user.getToken());
ObjectNode result = JacksonUtils.createEmptyJsonNode();
result.put(Constants.ACCESS_TOKEN, user.getToken());
result.put(Constants.TOKEN_TTL, authConfigs.getTokenValidityInSeconds());
result.put(Constants.GLOBAL_ADMIN, user.isGlobalAdmin());
result.put(Constants.USERNAME, user.getUserName());
return result;
}
// create Authentication class through username and password, the implement class is UsernamePasswordAuthenticationToken
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,
password);
try {
// use the method authenticate of AuthenticationManager(default implement is ProviderManager) to valid Authentication
Authentication authentication = authenticationManager.authenticate(authenticationToken);
// bind SecurityContext to Authentication
SecurityContextHolder.getContext().setAuthentication(authentication);
// generate Token
String token = jwtTokenManager.createToken(authentication);
// write Token to Http header
response.addHeader(NacosAuthConfig.AUTHORIZATION_HEADER, "Bearer " + token);
return RestResultUtils.success("Bearer " + token);
} catch (BadCredentialsException authentication) {
return RestResultUtils.failed(HttpStatus.UNAUTHORIZED.value(), null, "Login failed");
}
}
/**
* Update password.
*
* @param oldPassword old password
* @param newPassword new password
* @return Code 200 if update successfully, Code 401 if old password invalid, otherwise 500
*/
@PutMapping("/password")
@Deprecated
public RestResult<String> updatePassword(@RequestParam(value = "oldPassword") String oldPassword,
@RequestParam(value = "newPassword") String newPassword) {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = ((UserDetails) principal).getUsername();
User user = userDetailsService.getUserFromDatabase(username);
String password = user.getPassword();
// TODO: throw out more fine grained exceptions
try {
if (PasswordEncoderUtil.matches(oldPassword, password)) {
userDetailsService.updateUserPassword(username, PasswordEncoderUtil.encode(newPassword));
return RestResultUtils.success("Update password success");
}
return RestResultUtils.failed(HttpStatus.UNAUTHORIZED.value(), "Old password is invalid");
} catch (Exception e) {
return RestResultUtils.failed(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Update userpassword failed");
}
}
@Autowired
private NacosUserDetailsServiceImpl userDetailsService;
@Autowired
private NacosRoleServiceImpl roleService;
@Autowired
private AuthConfigs authConfigs;
@Autowired
private NacosAuthManager authManager;
/**
* Create a new user.
* @param username username
* @param password password
* @return ok if create succeed
* @throws IllegalArgumentException if user already exist
* @since 1.2.0
*/
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE)
@PostMapping
public Object createUser(@RequestParam String username, @RequestParam String password) {
User user = userDetailsService.getUserFromDatabase(username);
if (user != null) {
throw new IllegalArgumentException("user '" + username + "' already exist!");
}
userDetailsService.createUser(username, PasswordEncoderUtil.encode(password));
return RestResultUtils.success("create user ok!");
}
/**
* Delete an existed user.
* @param username username of user
* @return ok if deleted succeed, keep silent if user not exist
* @since 1.2.0
*/
@DeleteMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE)
public Object deleteUser(@RequestParam String username) {
List<RoleInfo> roleInfoList = roleService.getRoles(username);
if (roleInfoList != null) {
for (RoleInfo roleInfo : roleInfoList) {
if (roleInfo.getRole().equals(NacosRoleServiceImpl.GLOBAL_ADMIN_ROLE)) {
throw new IllegalArgumentException("cannot delete admin: " + username);
}
}
}
userDetailsService.deleteUser(username);
return RestResultUtils.success("delete user ok!");
}
/**
* Update an user.
* @param username username of user
* @param newPassword new password of user
* @param response http response
* @param request http request
* @return ok if update succeed
* @throws IllegalArgumentException if user not exist or oldPassword is incorrect
* @since 1.2.0
*/
@PutMapping
@Secured(resource = NacosAuthConfig.UPDATE_PASSWORD_ENTRY_POINT, action = ActionTypes.WRITE)
public Object updateUser(@RequestParam String username, @RequestParam String newPassword,
HttpServletResponse response, HttpServletRequest request) throws IOException {
// admin or same user
if (!hasPermission(username, request)) {
response.sendError(HttpServletResponse.SC_FORBIDDEN, "authorization failed!");
}
User user = userDetailsService.getUserFromDatabase(username);
if (user == null) {
throw new IllegalArgumentException("user " + username + " not exist!");
}
userDetailsService.updateUserPassword(username, PasswordEncoderUtil.encode(newPassword));
return RestResultUtils.success("update user ok!");
}
private boolean hasPermission(String username, HttpServletRequest request) {
if (!authConfigs.isAuthEnabled()) {
return true;
}
if (Objects.isNull(request.getAttribute(RequestUtil.NACOS_USER_KEY))) {
return false;
}
NacosUser user = (NacosUser) request.getAttribute(RequestUtil.NACOS_USER_KEY);
// admin
if (user.isGlobalAdmin()) {
return true;
}
// same user
return user.getUserName().equals(username);
}
/**
* Get paged users.
* @param pageNo number index of page
* @param pageSize size of page
* @return A collection of users, empty set if no user is found
* @since 1.2.0
*/
@GetMapping
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.READ)
public Object getUsers(@RequestParam int pageNo, @RequestParam int pageSize) {
return userDetailsService.getUsersFromDatabase(pageNo, pageSize);
}
/**
* Login to Nacos
*
* <p>
* This methods uses username and password to require a new token.
* @param username username of user
* @param password password
* @param response http response
* @param request http request
* @return new token of the user
* @throws AccessException if user info is incorrect
*/
@PostMapping("/login")
public Object login(@RequestParam String username, @RequestParam String password, HttpServletResponse response,
HttpServletRequest request) throws AccessException {
if (AuthSystemTypes.NACOS.name().equalsIgnoreCase(authConfigs.getNacosAuthSystemType())
|| AuthSystemTypes.LDAP.name().equalsIgnoreCase(authConfigs.getNacosAuthSystemType())) {
NacosUser user = (NacosUser) authManager.login(request);
response.addHeader(NacosAuthConfig.AUTHORIZATION_HEADER, NacosAuthConfig.TOKEN_PREFIX + user.getToken());
ObjectNode result = JacksonUtils.createEmptyJsonNode();
result.put(Constants.ACCESS_TOKEN, user.getToken());
result.put(Constants.TOKEN_TTL, authConfigs.getTokenValidityInSeconds());
result.put(Constants.GLOBAL_ADMIN, user.isGlobalAdmin());
result.put(Constants.USERNAME, user.getUserName());
return result;
}
// create Authentication class through username and password, the implement class
// is UsernamePasswordAuthenticationToken
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,
password);
try {
// use the method authenticate of AuthenticationManager(default implement is
// ProviderManager) to valid Authentication
Authentication authentication = authenticationManager.authenticate(authenticationToken);
// bind SecurityContext to Authentication
SecurityContextHolder.getContext().setAuthentication(authentication);
// generate Token
String token = jwtTokenManager.createToken(authentication);
// write Token to Http header
response.addHeader(NacosAuthConfig.AUTHORIZATION_HEADER, "Bearer " + token);
return RestResultUtils.success("Bearer " + token);
}
catch (BadCredentialsException authentication) {
return RestResultUtils.failed(HttpStatus.UNAUTHORIZED.value(), null, "Login failed");
}
}
/**
* Update password.
* @param oldPassword old password
* @param newPassword new password
* @return Code 200 if update successfully, Code 401 if old password invalid,
* otherwise 500
*/
@PutMapping("/password")
@Deprecated
public RestResult<String> updatePassword(@RequestParam(value = "oldPassword") String oldPassword,
@RequestParam(value = "newPassword") String newPassword) {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = ((UserDetails) principal).getUsername();
User user = userDetailsService.getUserFromDatabase(username);
String password = user.getPassword();
// TODO: throw out more fine grained exceptions
try {
if (PasswordEncoderUtil.matches(oldPassword, password)) {
userDetailsService.updateUserPassword(username, PasswordEncoderUtil.encode(newPassword));
return RestResultUtils.success("Update password success");
}
return RestResultUtils.failed(HttpStatus.UNAUTHORIZED.value(), "Old password is invalid");
}
catch (Exception e) {
return RestResultUtils.failed(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Update userpassword failed");
}
}
/**
* Fuzzy matching username.
* @param username username
* @return Matched username
*/
@GetMapping("/search")
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE)
public List<String> searchUsersLikeUsername(@RequestParam String username) {
return userDetailsService.findUserLikeUsername(username);
}
/**
* Fuzzy matching username.
*
* @param username username
* @return Matched username
*/
@GetMapping("/search")
@Secured(resource = NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX + "users", action = ActionTypes.WRITE)
public List<String> searchUsersLikeUsername(@RequestParam String username) {
return userDetailsService.findUserLikeUsername(username);
}
}

View File

@ -17,50 +17,50 @@
package com.alibaba.nacos.enums;
/**
* the enum of namespace.
* 0 : Global configuration 1 : Default private namespace 2 : Custom namespace.
* the enum of namespace. 0 : Global configuration 1 : Default private namespace 2 :
* Custom namespace.
*
* @author chenglu
* @date 2021-05-25 17:01
*/
public enum NamespaceTypeEnum {
/**
* Global configuration.
*/
GLOBAL(0, "Global configuration"),
/**
* Default private namespace.
*/
PRIVATE(1, "Default private namespace"),
/**
* Custom namespace.
*/
CUSTOM(2, "Custom namespace");
/**
* the namespace type.
*/
private final int type;
/**
* the description.
*/
private final String description;
NamespaceTypeEnum(int type, String description) {
this.type = type;
this.description = description;
}
public int getType() {
return type;
}
public String getDescription() {
return description;
}
}
/**
* Global configuration.
*/
GLOBAL(0, "Global configuration"),
/**
* Default private namespace.
*/
PRIVATE(1, "Default private namespace"),
/**
* Custom namespace.
*/
CUSTOM(2, "Custom namespace");
/**
* the namespace type.
*/
private final int type;
/**
* the description.
*/
private final String description;
NamespaceTypeEnum(int type, String description) {
this.type = type;
this.description = description;
}
public int getType() {
return type;
}
public String getDescription() {
return description;
}
}

View File

@ -36,41 +36,42 @@ import java.io.IOException;
* @author wfnuser
*/
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
private static final String TOKEN_PREFIX = "Bearer ";
private final JwtTokenManager tokenManager;
public JwtAuthenticationTokenFilter(JwtTokenManager tokenManager) {
this.tokenManager = tokenManager;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
String jwt = resolveToken(request);
if (StringUtils.isNotBlank(jwt) && SecurityContextHolder.getContext().getAuthentication() == null) {
this.tokenManager.validateToken(jwt);
Authentication authentication = this.tokenManager.getAuthentication(jwt);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
chain.doFilter(request, response);
}
/**
* Get token from header.
*/
private String resolveToken(HttpServletRequest request) {
String bearerToken = request.getHeader(NacosAuthConfig.AUTHORIZATION_HEADER);
if (StringUtils.isNotBlank(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) {
return bearerToken.substring(TOKEN_PREFIX.length());
}
String jwt = request.getParameter(Constants.ACCESS_TOKEN);
if (StringUtils.isNotBlank(jwt)) {
return jwt;
}
return null;
}
private static final String TOKEN_PREFIX = "Bearer ";
private final JwtTokenManager tokenManager;
public JwtAuthenticationTokenFilter(JwtTokenManager tokenManager) {
this.tokenManager = tokenManager;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
String jwt = resolveToken(request);
if (StringUtils.isNotBlank(jwt) && SecurityContextHolder.getContext().getAuthentication() == null) {
this.tokenManager.validateToken(jwt);
Authentication authentication = this.tokenManager.getAuthentication(jwt);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
chain.doFilter(request, response);
}
/**
* Get token from header.
*/
private String resolveToken(HttpServletRequest request) {
String bearerToken = request.getHeader(NacosAuthConfig.AUTHORIZATION_HEADER);
if (StringUtils.isNotBlank(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) {
return bearerToken.substring(TOKEN_PREFIX.length());
}
String jwt = request.getParameter(Constants.ACCESS_TOKEN);
if (StringUtils.isNotBlank(jwt)) {
return jwt;
}
return null;
}
}

View File

@ -22,74 +22,74 @@ package com.alibaba.nacos.model;
* @author diamond
*/
public class Namespace {
private String namespace;
private String namespaceShowName;
private int quota;
private int configCount;
/**
* see {@link com.alibaba.nacos.console.enums.NamespaceTypeEnum}.
*/
private int type;
public String getNamespaceShowName() {
return namespaceShowName;
}
public void setNamespaceShowName(String namespaceShowName) {
this.namespaceShowName = namespaceShowName;
}
public String getNamespace() {
return namespace;
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}
public Namespace() {
}
public Namespace(String namespace, String namespaceShowName) {
this.namespace = namespace;
this.namespaceShowName = namespaceShowName;
}
public Namespace(String namespace, String namespaceShowName, int quota, int configCount, int type) {
this.namespace = namespace;
this.namespaceShowName = namespaceShowName;
this.quota = quota;
this.configCount = configCount;
this.type = type;
}
public int getQuota() {
return quota;
}
public void setQuota(int quota) {
this.quota = quota;
}
public int getConfigCount() {
return configCount;
}
public void setConfigCount(int configCount) {
this.configCount = configCount;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
private String namespace;
private String namespaceShowName;
private int quota;
private int configCount;
/**
* see {@link com.alibaba.nacos.console.enums.NamespaceTypeEnum}.
*/
private int type;
public String getNamespaceShowName() {
return namespaceShowName;
}
public void setNamespaceShowName(String namespaceShowName) {
this.namespaceShowName = namespaceShowName;
}
public String getNamespace() {
return namespace;
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}
public Namespace() {
}
public Namespace(String namespace, String namespaceShowName) {
this.namespace = namespace;
this.namespaceShowName = namespaceShowName;
}
public Namespace(String namespace, String namespaceShowName, int quota, int configCount, int type) {
this.namespace = namespace;
this.namespaceShowName = namespaceShowName;
this.quota = quota;
this.configCount = configCount;
this.type = type;
}
public int getQuota() {
return quota;
}
public void setQuota(int quota) {
this.quota = quota;
}
public int getConfigCount() {
return configCount;
}
public void setConfigCount(int configCount) {
this.configCount = configCount;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}

View File

@ -40,64 +40,60 @@ import java.util.List;
*/
@Component
public class JwtTokenManager {
private static final String AUTHORITIES_KEY = "auth";
@Autowired
private AuthConfigs authConfigs;
/**
* Create token.
*
* @param authentication auth info
* @return token
*/
public String createToken(Authentication authentication) {
return createToken(authentication.getName());
}
/**
* Create token.
*
* @param userName auth info
* @return token
*/
public String createToken(String userName) {
long now = System.currentTimeMillis();
Date validity;
validity = new Date(now + authConfigs.getTokenValidityInSeconds() * 1000L);
Claims claims = Jwts.claims().setSubject(userName);
return Jwts.builder().setClaims(claims).setExpiration(validity)
.signWith(Keys.hmacShaKeyFor(authConfigs.getSecretKeyBytes()), SignatureAlgorithm.HS256).compact();
}
/**
* Get auth Info.
*
* @param token token
* @return auth info
*/
public Authentication getAuthentication(String token) {
Claims claims = Jwts.parserBuilder().setSigningKey(authConfigs.getSecretKeyBytes()).build()
.parseClaimsJws(token).getBody();
List<GrantedAuthority> authorities = AuthorityUtils
.commaSeparatedStringToAuthorityList((String) claims.get(AUTHORITIES_KEY));
User principal = new User(claims.getSubject(), "", authorities);
return new UsernamePasswordAuthenticationToken(principal, "", authorities);
}
/**
* validate token.
*
* @param token token
*/
public void validateToken(String token) {
Jwts.parserBuilder().setSigningKey(authConfigs.getSecretKeyBytes()).build().parseClaimsJws(token);
}
private static final String AUTHORITIES_KEY = "auth";
@Autowired
private AuthConfigs authConfigs;
/**
* Create token.
* @param authentication auth info
* @return token
*/
public String createToken(Authentication authentication) {
return createToken(authentication.getName());
}
/**
* Create token.
* @param userName auth info
* @return token
*/
public String createToken(String userName) {
long now = System.currentTimeMillis();
Date validity;
validity = new Date(now + authConfigs.getTokenValidityInSeconds() * 1000L);
Claims claims = Jwts.claims().setSubject(userName);
return Jwts.builder().setClaims(claims).setExpiration(validity)
.signWith(Keys.hmacShaKeyFor(authConfigs.getSecretKeyBytes()), SignatureAlgorithm.HS256).compact();
}
/**
* Get auth Info.
* @param token token
* @return auth info
*/
public Authentication getAuthentication(String token) {
Claims claims = Jwts.parserBuilder().setSigningKey(authConfigs.getSecretKeyBytes()).build()
.parseClaimsJws(token).getBody();
List<GrantedAuthority> authorities = AuthorityUtils
.commaSeparatedStringToAuthorityList((String) claims.get(AUTHORITIES_KEY));
User principal = new User(claims.getSubject(), "", authorities);
return new UsernamePasswordAuthenticationToken(principal, "", authorities);
}
/**
* validate token.
* @param token token
*/
public void validateToken(String token) {
Jwts.parserBuilder().setSigningKey(authConfigs.getSecretKeyBytes()).build().parseClaimsJws(token);
}
}

View File

@ -45,7 +45,6 @@ import java.util.List;
import static com.alibaba.nacos.security.nacos.roles.NacosRoleServiceImpl.GLOBAL_ADMIN_ROLE;
/**
* LDAP auth provider.
*
@ -53,114 +52,121 @@ import static com.alibaba.nacos.security.nacos.roles.NacosRoleServiceImpl.GLOBAL
*/
@Component
public class LdapAuthenticationProvider implements AuthenticationProvider {
private static final Logger LOG = LoggerFactory.getLogger(LdapAuthenticationProvider.class);
private static final String FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
private static final String TIMEOUT = "com.sun.jndi.ldap.connect.timeout";
private static final String DEFAULT_PASSWORD = "nacos";
private static final String LDAP_PREFIX = "LDAP_";
private static final String DEFAULT_SECURITY_AUTH = "simple";
@Autowired
private NacosUserDetailsServiceImpl userDetailsService;
@Autowired
private NacosRoleServiceImpl nacosRoleService;
@Value(("${nacos.core.auth.ldap.url:ldap://localhost:389}"))
private String ldapUrl;
@Value(("${nacos.core.auth.ldap.timeout:3000}"))
private String time;
@Value(("${nacos.core.auth.ldap.userdn:cn={0},ou=user,dc=company,dc=com}"))
private String userNamePattern;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = (String) authentication.getPrincipal();
String password = (String) authentication.getCredentials();
if (isAdmin(username)) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (PasswordEncoderUtil.matches(password, userDetails.getPassword())) {
return new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities());
} else {
return null;
}
}
if (!ldapLogin(username, password)) {
return null;
}
UserDetails userDetails;
try {
userDetails = userDetailsService.loadUserByUsername(LDAP_PREFIX + username);
} catch (UsernameNotFoundException exception) {
String nacosPassword = PasswordEncoderUtil.encode(DEFAULT_PASSWORD);
userDetailsService.createUser(LDAP_PREFIX + username, nacosPassword);
User user = new User();
user.setUsername(LDAP_PREFIX + username);
user.setPassword(nacosPassword);
userDetails = new NacosUserDetails(user);
}
return new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities());
}
private boolean isAdmin(String username) {
List<RoleInfo> roleInfos = nacosRoleService.getRoles(username);
if (CollectionUtils.isEmpty(roleInfos)) {
return false;
}
for (RoleInfo roleinfo : roleInfos) {
if (GLOBAL_ADMIN_ROLE.equals(roleinfo.getRole())) {
return true;
}
}
return false;
}
private boolean ldapLogin(String username, String password) throws AuthenticationException {
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
env.put(Context.PROVIDER_URL, ldapUrl);
env.put(Context.SECURITY_AUTHENTICATION, DEFAULT_SECURITY_AUTH);
env.put(Context.SECURITY_PRINCIPAL, userNamePattern.replace("{0}", username));
env.put(Context.SECURITY_CREDENTIALS, password);
env.put(TIMEOUT, time);
LdapContext ctx = null;
try {
ctx = new InitialLdapContext(env, null);
} catch (CommunicationException e) {
throw new RuntimeException("LDAP Service connect timeout");
} catch (Exception e) {
LOG.warn("Exception cause by:{}", e.getMessage());
return false;
} finally {
closeContext(ctx);
}
return true;
}
@Override
public boolean supports(Class<?> aClass) {
return aClass.equals(UsernamePasswordAuthenticationToken.class);
}
private void closeContext(DirContext ctx) {
if (ctx != null) {
try {
ctx.close();
} catch (Exception e) {
LOG.error("Exception closing context", e);
}
}
}
private static final Logger LOG = LoggerFactory.getLogger(LdapAuthenticationProvider.class);
private static final String FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
private static final String TIMEOUT = "com.sun.jndi.ldap.connect.timeout";
private static final String DEFAULT_PASSWORD = "nacos";
private static final String LDAP_PREFIX = "LDAP_";
private static final String DEFAULT_SECURITY_AUTH = "simple";
@Autowired
private NacosUserDetailsServiceImpl userDetailsService;
@Autowired
private NacosRoleServiceImpl nacosRoleService;
@Value(("${nacos.core.auth.ldap.url:ldap://localhost:389}"))
private String ldapUrl;
@Value(("${nacos.core.auth.ldap.timeout:3000}"))
private String time;
@Value(("${nacos.core.auth.ldap.userdn:cn={0},ou=user,dc=company,dc=com}"))
private String userNamePattern;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = (String) authentication.getPrincipal();
String password = (String) authentication.getCredentials();
if (isAdmin(username)) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (PasswordEncoderUtil.matches(password, userDetails.getPassword())) {
return new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities());
}
else {
return null;
}
}
if (!ldapLogin(username, password)) {
return null;
}
UserDetails userDetails;
try {
userDetails = userDetailsService.loadUserByUsername(LDAP_PREFIX + username);
}
catch (UsernameNotFoundException exception) {
String nacosPassword = PasswordEncoderUtil.encode(DEFAULT_PASSWORD);
userDetailsService.createUser(LDAP_PREFIX + username, nacosPassword);
User user = new User();
user.setUsername(LDAP_PREFIX + username);
user.setPassword(nacosPassword);
userDetails = new NacosUserDetails(user);
}
return new UsernamePasswordAuthenticationToken(userDetails, password, userDetails.getAuthorities());
}
private boolean isAdmin(String username) {
List<RoleInfo> roleInfos = nacosRoleService.getRoles(username);
if (CollectionUtils.isEmpty(roleInfos)) {
return false;
}
for (RoleInfo roleinfo : roleInfos) {
if (GLOBAL_ADMIN_ROLE.equals(roleinfo.getRole())) {
return true;
}
}
return false;
}
private boolean ldapLogin(String username, String password) throws AuthenticationException {
Hashtable<String, String> env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
env.put(Context.PROVIDER_URL, ldapUrl);
env.put(Context.SECURITY_AUTHENTICATION, DEFAULT_SECURITY_AUTH);
env.put(Context.SECURITY_PRINCIPAL, userNamePattern.replace("{0}", username));
env.put(Context.SECURITY_CREDENTIALS, password);
env.put(TIMEOUT, time);
LdapContext ctx = null;
try {
ctx = new InitialLdapContext(env, null);
}
catch (CommunicationException e) {
throw new RuntimeException("LDAP Service connect timeout");
}
catch (Exception e) {
LOG.warn("Exception cause by:{}", e.getMessage());
return false;
}
finally {
closeContext(ctx);
}
return true;
}
@Override
public boolean supports(Class<?> aClass) {
return aClass.equals(UsernamePasswordAuthenticationToken.class);
}
private void closeContext(DirContext ctx) {
if (ctx != null) {
try {
ctx.close();
}
catch (Exception e) {
LOG.error("Exception closing context", e);
}
}
}
}

View File

@ -44,95 +44,97 @@ import org.springframework.web.cors.CorsUtils;
*/
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class NacosAuthConfig extends WebSecurityConfigurerAdapter {
public static final String AUTHORIZATION_HEADER = "Authorization";
public static final String SECURITY_IGNORE_URLS_SPILT_CHAR = ",";
public static final String LOGIN_ENTRY_POINT = "/v1/auth/login";
public static final String TOKEN_BASED_AUTH_ENTRY_POINT = "/v1/auth/**";
public static final String TOKEN_PREFIX = "Bearer ";
public static final String CONSOLE_RESOURCE_NAME_PREFIX = "console/";
public static final String UPDATE_PASSWORD_ENTRY_POINT = CONSOLE_RESOURCE_NAME_PREFIX + "user/password";
private static final String DEFAULT_ALL_PATH_PATTERN = "/**";
private static final String PROPERTY_IGNORE_URLS = "nacos.security.ignore.urls";
public static final String AUTHORIZATION_HEADER = "Authorization";
public static final String SECURITY_IGNORE_URLS_SPILT_CHAR = ",";
public static final String LOGIN_ENTRY_POINT = "/v1/auth/login";
public static final String TOKEN_BASED_AUTH_ENTRY_POINT = "/v1/auth/**";
public static final String TOKEN_PREFIX = "Bearer ";
public static final String CONSOLE_RESOURCE_NAME_PREFIX = "console/";
public static final String UPDATE_PASSWORD_ENTRY_POINT = CONSOLE_RESOURCE_NAME_PREFIX + "user/password";
private static final String DEFAULT_ALL_PATH_PATTERN = "/**";
private static final String PROPERTY_IGNORE_URLS = "nacos.security.ignore.urls";
@Autowired
private Environment env;
@Autowired
private JwtTokenManager tokenProvider;
@Autowired
private AuthConfigs authConfigs;
@Autowired
private NacosUserDetailsServiceImpl userDetailsService;
@Autowired
private LdapAuthenticationProvider ldapAuthenticationProvider;
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
public void configure(WebSecurity web) {
String ignoreUrls = null;
if (AuthSystemTypes.NACOS.name().equalsIgnoreCase(authConfigs.getNacosAuthSystemType())) {
ignoreUrls = DEFAULT_ALL_PATH_PATTERN;
}
else if (AuthSystemTypes.LDAP.name().equalsIgnoreCase(authConfigs.getNacosAuthSystemType())) {
ignoreUrls = DEFAULT_ALL_PATH_PATTERN;
}
if (StringUtils.isBlank(authConfigs.getNacosAuthSystemType())) {
ignoreUrls = env.getProperty(PROPERTY_IGNORE_URLS, DEFAULT_ALL_PATH_PATTERN);
}
if (StringUtils.isNotBlank(ignoreUrls)) {
for (String each : ignoreUrls.trim().split(SECURITY_IGNORE_URLS_SPILT_CHAR)) {
web.ignoring().antMatchers(each.trim());
}
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
if (AuthSystemTypes.NACOS.name().equalsIgnoreCase(authConfigs.getNacosAuthSystemType())) {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
else if (AuthSystemTypes.LDAP.name().equalsIgnoreCase(authConfigs.getNacosAuthSystemType())) {
auth.authenticationProvider(ldapAuthenticationProvider);
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
if (StringUtils.isBlank(authConfigs.getNacosAuthSystemType())) {
http.csrf().disable().cors()// We don't need CSRF for JWT based authentication
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
.authorizeRequests().requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.antMatchers(LOGIN_ENTRY_POINT).permitAll().and().authorizeRequests()
.antMatchers(TOKEN_BASED_AUTH_ENTRY_POINT).authenticated().and().exceptionHandling()
.authenticationEntryPoint(new JwtAuthenticationEntryPoint());
// disable cache
http.headers().cacheControl();
http.addFilterBefore(new JwtAuthenticationTokenFilter(tokenProvider),
UsernamePasswordAuthenticationFilter.class);
}
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
private Environment env;
@Autowired
private JwtTokenManager tokenProvider;
@Autowired
private AuthConfigs authConfigs;
@Autowired
private NacosUserDetailsServiceImpl userDetailsService;
@Autowired
private LdapAuthenticationProvider ldapAuthenticationProvider;
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
public void configure(WebSecurity web) {
String ignoreUrls = null;
if (AuthSystemTypes.NACOS.name().equalsIgnoreCase(authConfigs.getNacosAuthSystemType())) {
ignoreUrls = DEFAULT_ALL_PATH_PATTERN;
} else if (AuthSystemTypes.LDAP.name().equalsIgnoreCase(authConfigs.getNacosAuthSystemType())) {
ignoreUrls = DEFAULT_ALL_PATH_PATTERN;
}
if (StringUtils.isBlank(authConfigs.getNacosAuthSystemType())) {
ignoreUrls = env.getProperty(PROPERTY_IGNORE_URLS, DEFAULT_ALL_PATH_PATTERN);
}
if (StringUtils.isNotBlank(ignoreUrls)) {
for (String each : ignoreUrls.trim().split(SECURITY_IGNORE_URLS_SPILT_CHAR)) {
web.ignoring().antMatchers(each.trim());
}
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
if (AuthSystemTypes.NACOS.name().equalsIgnoreCase(authConfigs.getNacosAuthSystemType())) {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
} else if (AuthSystemTypes.LDAP.name().equalsIgnoreCase(authConfigs.getNacosAuthSystemType())) {
auth.authenticationProvider(ldapAuthenticationProvider);
}
}
@Override
protected void configure(HttpSecurity http) throws Exception {
if (StringUtils.isBlank(authConfigs.getNacosAuthSystemType())) {
http.csrf().disable().cors()// We don't need CSRF for JWT based authentication
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().authorizeRequests().requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.antMatchers(LOGIN_ENTRY_POINT).permitAll()
.and().authorizeRequests().antMatchers(TOKEN_BASED_AUTH_ENTRY_POINT).authenticated()
.and().exceptionHandling().authenticationEntryPoint(new JwtAuthenticationEntryPoint());
// disable cache
http.headers().cacheControl();
http.addFilterBefore(new JwtAuthenticationTokenFilter(tokenProvider),
UsernamePasswordAuthenticationFilter.class);
}
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}

View File

@ -48,157 +48,164 @@ import java.util.List;
*/
@Component
public class NacosAuthManager implements AuthManager {
private static final String TOKEN_PREFIX = "Bearer ";
private static final String PARAM_USERNAME = "username";
private static final String PARAM_PASSWORD = "password";
@Autowired
private JwtTokenManager tokenManager;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private NacosRoleServiceImpl roleService;
@Override
public User login(Object request) throws AccessException {
HttpServletRequest req = (HttpServletRequest) request;
String token = resolveToken(req);
if (StringUtils.isBlank(token)) {
throw new AccessException("user not found!");
}
try {
tokenManager.validateToken(token);
} catch (ExpiredJwtException e) {
throw new AccessException("token expired!");
} catch (Exception e) {
throw new AccessException("token invalid!");
}
Authentication authentication = tokenManager.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
String username = authentication.getName();
NacosUser user = new NacosUser();
user.setUserName(username);
user.setToken(token);
List<RoleInfo> roleInfoList = roleService.getRoles(username);
if (roleInfoList != null) {
for (RoleInfo roleInfo : roleInfoList) {
if (roleInfo.getRole().equals(NacosRoleServiceImpl.GLOBAL_ADMIN_ROLE)) {
user.setGlobalAdmin(true);
break;
}
}
}
req.setAttribute(RequestUtil.NACOS_USER_KEY, user);
return user;
}
@Override
public User loginRemote(Object request) throws AccessException {
Request req = (Request) request;
String token = resolveToken(req);
if (StringUtils.isBlank(token)) {
throw new AccessException("user not found!");
}
try {
tokenManager.validateToken(token);
} catch (ExpiredJwtException e) {
throw new AccessException("token expired!");
} catch (Exception e) {
throw new AccessException("token invalid!");
}
Authentication authentication = tokenManager.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
String username = authentication.getName();
NacosUser user = new NacosUser();
user.setUserName(username);
user.setToken(token);
List<RoleInfo> roleInfoList = roleService.getRoles(username);
if (roleInfoList != null) {
for (RoleInfo roleInfo : roleInfoList) {
if (roleInfo.getRole().equals(NacosRoleServiceImpl.GLOBAL_ADMIN_ROLE)) {
user.setGlobalAdmin(true);
break;
}
}
}
return user;
}
@Override
public void auth(Permission permission, User user) throws AccessException {
if (Loggers.AUTH.isDebugEnabled()) {
Loggers.AUTH.debug("auth permission: {}, user: {}", permission, user);
}
if (!roleService.hasPermission(user.getUserName(), permission)) {
throw new AccessException("authorization failed!");
}
}
/**
* Get token from header.
*/
private String resolveToken(HttpServletRequest request) throws AccessException {
String bearerToken = request.getHeader(NacosAuthConfig.AUTHORIZATION_HEADER);
if (StringUtils.isNotBlank(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) {
return bearerToken.substring(7);
}
bearerToken = request.getParameter(Constants.ACCESS_TOKEN);
if (StringUtils.isBlank(bearerToken)) {
String userName = request.getParameter(PARAM_USERNAME);
String password = request.getParameter(PARAM_PASSWORD);
bearerToken = resolveTokenFromUser(userName, password);
}
return bearerToken;
}
/**
* Get token from header.
*/
private String resolveToken(Request request) throws AccessException {
String bearerToken = request.getHeader(NacosAuthConfig.AUTHORIZATION_HEADER);
if (StringUtils.isNotBlank(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) {
return bearerToken.substring(7);
}
bearerToken = request.getHeader(Constants.ACCESS_TOKEN);
if (StringUtils.isBlank(bearerToken)) {
String userName = request.getHeader(PARAM_USERNAME);
String password = request.getHeader(PARAM_PASSWORD);
bearerToken = resolveTokenFromUser(userName, password);
}
return bearerToken;
}
private String resolveTokenFromUser(String userName, String rawPassword) throws AccessException {
String finalName;
Authentication authenticate;
try {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userName,
rawPassword);
authenticate = authenticationManager.authenticate(authenticationToken);
} catch (AuthenticationException e) {
throw new AccessException("unknown user!");
}
if (null == authenticate || StringUtils.isBlank(authenticate.getName())) {
finalName = userName;
} else {
finalName = authenticate.getName();
}
return tokenManager.createToken(finalName);
}
private static final String TOKEN_PREFIX = "Bearer ";
private static final String PARAM_USERNAME = "username";
private static final String PARAM_PASSWORD = "password";
@Autowired
private JwtTokenManager tokenManager;
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private NacosRoleServiceImpl roleService;
@Override
public User login(Object request) throws AccessException {
HttpServletRequest req = (HttpServletRequest) request;
String token = resolveToken(req);
if (StringUtils.isBlank(token)) {
throw new AccessException("user not found!");
}
try {
tokenManager.validateToken(token);
}
catch (ExpiredJwtException e) {
throw new AccessException("token expired!");
}
catch (Exception e) {
throw new AccessException("token invalid!");
}
Authentication authentication = tokenManager.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
String username = authentication.getName();
NacosUser user = new NacosUser();
user.setUserName(username);
user.setToken(token);
List<RoleInfo> roleInfoList = roleService.getRoles(username);
if (roleInfoList != null) {
for (RoleInfo roleInfo : roleInfoList) {
if (roleInfo.getRole().equals(NacosRoleServiceImpl.GLOBAL_ADMIN_ROLE)) {
user.setGlobalAdmin(true);
break;
}
}
}
req.setAttribute(RequestUtil.NACOS_USER_KEY, user);
return user;
}
@Override
public User loginRemote(Object request) throws AccessException {
Request req = (Request) request;
String token = resolveToken(req);
if (StringUtils.isBlank(token)) {
throw new AccessException("user not found!");
}
try {
tokenManager.validateToken(token);
}
catch (ExpiredJwtException e) {
throw new AccessException("token expired!");
}
catch (Exception e) {
throw new AccessException("token invalid!");
}
Authentication authentication = tokenManager.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
String username = authentication.getName();
NacosUser user = new NacosUser();
user.setUserName(username);
user.setToken(token);
List<RoleInfo> roleInfoList = roleService.getRoles(username);
if (roleInfoList != null) {
for (RoleInfo roleInfo : roleInfoList) {
if (roleInfo.getRole().equals(NacosRoleServiceImpl.GLOBAL_ADMIN_ROLE)) {
user.setGlobalAdmin(true);
break;
}
}
}
return user;
}
@Override
public void auth(Permission permission, User user) throws AccessException {
if (Loggers.AUTH.isDebugEnabled()) {
Loggers.AUTH.debug("auth permission: {}, user: {}", permission, user);
}
if (!roleService.hasPermission(user.getUserName(), permission)) {
throw new AccessException("authorization failed!");
}
}
/**
* Get token from header.
*/
private String resolveToken(HttpServletRequest request) throws AccessException {
String bearerToken = request.getHeader(NacosAuthConfig.AUTHORIZATION_HEADER);
if (StringUtils.isNotBlank(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) {
return bearerToken.substring(7);
}
bearerToken = request.getParameter(Constants.ACCESS_TOKEN);
if (StringUtils.isBlank(bearerToken)) {
String userName = request.getParameter(PARAM_USERNAME);
String password = request.getParameter(PARAM_PASSWORD);
bearerToken = resolveTokenFromUser(userName, password);
}
return bearerToken;
}
/**
* Get token from header.
*/
private String resolveToken(Request request) throws AccessException {
String bearerToken = request.getHeader(NacosAuthConfig.AUTHORIZATION_HEADER);
if (StringUtils.isNotBlank(bearerToken) && bearerToken.startsWith(TOKEN_PREFIX)) {
return bearerToken.substring(7);
}
bearerToken = request.getHeader(Constants.ACCESS_TOKEN);
if (StringUtils.isBlank(bearerToken)) {
String userName = request.getHeader(PARAM_USERNAME);
String password = request.getHeader(PARAM_PASSWORD);
bearerToken = resolveTokenFromUser(userName, password);
}
return bearerToken;
}
private String resolveTokenFromUser(String userName, String rawPassword) throws AccessException {
String finalName;
Authentication authenticate;
try {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userName,
rawPassword);
authenticate = authenticationManager.authenticate(authenticationToken);
}
catch (AuthenticationException e) {
throw new AccessException("unknown user!");
}
if (null == authenticate || StringUtils.isBlank(authenticate.getName())) {
finalName = userName;
}
else {
finalName = authenticate.getName();
}
return tokenManager.createToken(finalName);
}
}

View File

@ -49,200 +49,201 @@ import java.util.regex.Pattern;
*/
@Service
public class NacosRoleServiceImpl {
public static final String GLOBAL_ADMIN_ROLE = "ROLE_ADMIN";
private static final int DEFAULT_PAGE_NO = 1;
@Autowired
private AuthConfigs authConfigs;
@Autowired
private RolePersistService rolePersistService;
@Autowired
private NacosUserDetailsServiceImpl userDetailsService;
@Autowired
private PermissionPersistService permissionPersistService;
private volatile Set<String> roleSet = new ConcurrentHashSet<>();
private volatile Map<String, List<RoleInfo>> roleInfoMap = new ConcurrentHashMap<>();
private volatile Map<String, List<PermissionInfo>> permissionInfoMap = new ConcurrentHashMap<>();
@Scheduled(initialDelay = 5000, fixedDelay = 15000)
private void reload() {
try {
Page<RoleInfo> roleInfoPage = rolePersistService
.getRolesByUserName(StringUtils.EMPTY, DEFAULT_PAGE_NO, Integer.MAX_VALUE);
if (roleInfoPage == null) {
return;
}
Set<String> tmpRoleSet = new HashSet<>(16);
Map<String, List<RoleInfo>> tmpRoleInfoMap = new ConcurrentHashMap<>(16);
for (RoleInfo roleInfo : roleInfoPage.getPageItems()) {
if (!tmpRoleInfoMap.containsKey(roleInfo.getUsername())) {
tmpRoleInfoMap.put(roleInfo.getUsername(), new ArrayList<>());
}
tmpRoleInfoMap.get(roleInfo.getUsername()).add(roleInfo);
tmpRoleSet.add(roleInfo.getRole());
}
Map<String, List<PermissionInfo>> tmpPermissionInfoMap = new ConcurrentHashMap<>(16);
for (String role : tmpRoleSet) {
Page<PermissionInfo> permissionInfoPage = permissionPersistService
.getPermissions(role, DEFAULT_PAGE_NO, Integer.MAX_VALUE);
tmpPermissionInfoMap.put(role, permissionInfoPage.getPageItems());
}
roleSet = tmpRoleSet;
roleInfoMap = tmpRoleInfoMap;
permissionInfoMap = tmpPermissionInfoMap;
} catch (Exception e) {
Loggers.AUTH.warn("[LOAD-ROLES] load failed", e);
}
}
/**
* Determine if the user has permission of the resource.
*
* <p>Note if the user has many roles, this method returns true if any one role of the user has the desired
* permission.
*
* @param username user info
* @param permission permission to auth
* @return true if granted, false otherwise
*/
public boolean hasPermission(String username, Permission permission) {
//update password
if (NacosAuthConfig.UPDATE_PASSWORD_ENTRY_POINT.equals(permission.getResource())) {
return true;
}
List<RoleInfo> roleInfoList = getRoles(username);
if (Collections.isEmpty(roleInfoList)) {
return false;
}
// Global admin pass:
for (RoleInfo roleInfo : roleInfoList) {
if (GLOBAL_ADMIN_ROLE.equals(roleInfo.getRole())) {
return true;
}
}
// Old global admin can pass resource 'console/':
if (permission.getResource().startsWith(NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX)) {
return false;
}
// For other roles, use a pattern match to decide if pass or not.
for (RoleInfo roleInfo : roleInfoList) {
List<PermissionInfo> permissionInfoList = getPermissions(roleInfo.getRole());
if (Collections.isEmpty(permissionInfoList)) {
continue;
}
for (PermissionInfo permissionInfo : permissionInfoList) {
String permissionResource = permissionInfo.getResource().replaceAll("\\*", ".*");
String permissionAction = permissionInfo.getAction();
if (permissionAction.contains(permission.getAction()) && Pattern
.matches(permissionResource, permission.getResource())) {
return true;
}
}
}
return false;
}
public List<RoleInfo> getRoles(String username) {
List<RoleInfo> roleInfoList = roleInfoMap.get(username);
if (!authConfigs.isCachingEnabled()) {
Page<RoleInfo> roleInfoPage = getRolesFromDatabase(username, DEFAULT_PAGE_NO, Integer.MAX_VALUE);
if (roleInfoPage != null) {
roleInfoList = roleInfoPage.getPageItems();
}
}
return roleInfoList;
}
public Page<RoleInfo> getRolesFromDatabase(String userName, int pageNo, int pageSize) {
Page<RoleInfo> roles = rolePersistService.getRolesByUserName(userName, pageNo, pageSize);
if (roles == null) {
return new Page<>();
}
return roles;
}
public List<PermissionInfo> getPermissions(String role) {
List<PermissionInfo> permissionInfoList = permissionInfoMap.get(role);
if (!authConfigs.isCachingEnabled()) {
Page<PermissionInfo> permissionInfoPage = getPermissionsFromDatabase(role, DEFAULT_PAGE_NO, Integer.MAX_VALUE);
if (permissionInfoPage != null) {
permissionInfoList = permissionInfoPage.getPageItems();
}
}
return permissionInfoList;
}
public Page<PermissionInfo> getPermissionsByRoleFromDatabase(String role, int pageNo, int pageSize) {
return permissionPersistService.getPermissions(role, pageNo, pageSize);
}
/**
* Add role.
*
* @param role role name
* @param username user name
*/
public void addRole(String role, String username) {
if (userDetailsService.getUserFromDatabase(username) == null) {
throw new IllegalArgumentException("user '" + username + "' not found!");
}
if (GLOBAL_ADMIN_ROLE.equals(role)) {
throw new IllegalArgumentException("role '" + GLOBAL_ADMIN_ROLE + "' is not permitted to create!");
}
rolePersistService.addRole(role, username);
roleSet.add(role);
}
public void deleteRole(String role, String userName) {
rolePersistService.deleteRole(role, userName);
}
public void deleteRole(String role) {
rolePersistService.deleteRole(role);
roleSet.remove(role);
}
public Page<PermissionInfo> getPermissionsFromDatabase(String role, int pageNo, int pageSize) {
Page<PermissionInfo> pageInfo = permissionPersistService.getPermissions(role, pageNo, pageSize);
if (pageInfo == null) {
return new Page<>();
}
return pageInfo;
}
/**
* Add permission.
*
* @param role role name
* @param resource resource
* @param action action
*/
public void addPermission(String role, String resource, String action) {
if (!roleSet.contains(role)) {
throw new IllegalArgumentException("role " + role + " not found!");
}
permissionPersistService.addPermission(role, resource, action);
}
public void deletePermission(String role, String resource, String action) {
permissionPersistService.deletePermission(role, resource, action);
}
public List<String> findRolesLikeRoleName(String role) {
return rolePersistService.findRolesLikeRoleName(role);
}
public static final String GLOBAL_ADMIN_ROLE = "ROLE_ADMIN";
private static final int DEFAULT_PAGE_NO = 1;
@Autowired
private AuthConfigs authConfigs;
@Autowired
private RolePersistService rolePersistService;
@Autowired
private NacosUserDetailsServiceImpl userDetailsService;
@Autowired
private PermissionPersistService permissionPersistService;
private volatile Set<String> roleSet = new ConcurrentHashSet<>();
private volatile Map<String, List<RoleInfo>> roleInfoMap = new ConcurrentHashMap<>();
private volatile Map<String, List<PermissionInfo>> permissionInfoMap = new ConcurrentHashMap<>();
@Scheduled(initialDelay = 5000, fixedDelay = 15000)
private void reload() {
try {
Page<RoleInfo> roleInfoPage = rolePersistService.getRolesByUserName(StringUtils.EMPTY, DEFAULT_PAGE_NO,
Integer.MAX_VALUE);
if (roleInfoPage == null) {
return;
}
Set<String> tmpRoleSet = new HashSet<>(16);
Map<String, List<RoleInfo>> tmpRoleInfoMap = new ConcurrentHashMap<>(16);
for (RoleInfo roleInfo : roleInfoPage.getPageItems()) {
if (!tmpRoleInfoMap.containsKey(roleInfo.getUsername())) {
tmpRoleInfoMap.put(roleInfo.getUsername(), new ArrayList<>());
}
tmpRoleInfoMap.get(roleInfo.getUsername()).add(roleInfo);
tmpRoleSet.add(roleInfo.getRole());
}
Map<String, List<PermissionInfo>> tmpPermissionInfoMap = new ConcurrentHashMap<>(16);
for (String role : tmpRoleSet) {
Page<PermissionInfo> permissionInfoPage = permissionPersistService.getPermissions(role, DEFAULT_PAGE_NO,
Integer.MAX_VALUE);
tmpPermissionInfoMap.put(role, permissionInfoPage.getPageItems());
}
roleSet = tmpRoleSet;
roleInfoMap = tmpRoleInfoMap;
permissionInfoMap = tmpPermissionInfoMap;
}
catch (Exception e) {
Loggers.AUTH.warn("[LOAD-ROLES] load failed", e);
}
}
/**
* Determine if the user has permission of the resource.
*
* <p>
* Note if the user has many roles, this method returns true if any one role of the
* user has the desired permission.
* @param username user info
* @param permission permission to auth
* @return true if granted, false otherwise
*/
public boolean hasPermission(String username, Permission permission) {
// update password
if (NacosAuthConfig.UPDATE_PASSWORD_ENTRY_POINT.equals(permission.getResource())) {
return true;
}
List<RoleInfo> roleInfoList = getRoles(username);
if (Collections.isEmpty(roleInfoList)) {
return false;
}
// Global admin pass:
for (RoleInfo roleInfo : roleInfoList) {
if (GLOBAL_ADMIN_ROLE.equals(roleInfo.getRole())) {
return true;
}
}
// Old global admin can pass resource 'console/':
if (permission.getResource().startsWith(NacosAuthConfig.CONSOLE_RESOURCE_NAME_PREFIX)) {
return false;
}
// For other roles, use a pattern match to decide if pass or not.
for (RoleInfo roleInfo : roleInfoList) {
List<PermissionInfo> permissionInfoList = getPermissions(roleInfo.getRole());
if (Collections.isEmpty(permissionInfoList)) {
continue;
}
for (PermissionInfo permissionInfo : permissionInfoList) {
String permissionResource = permissionInfo.getResource().replaceAll("\\*", ".*");
String permissionAction = permissionInfo.getAction();
if (permissionAction.contains(permission.getAction())
&& Pattern.matches(permissionResource, permission.getResource())) {
return true;
}
}
}
return false;
}
public List<RoleInfo> getRoles(String username) {
List<RoleInfo> roleInfoList = roleInfoMap.get(username);
if (!authConfigs.isCachingEnabled()) {
Page<RoleInfo> roleInfoPage = getRolesFromDatabase(username, DEFAULT_PAGE_NO, Integer.MAX_VALUE);
if (roleInfoPage != null) {
roleInfoList = roleInfoPage.getPageItems();
}
}
return roleInfoList;
}
public Page<RoleInfo> getRolesFromDatabase(String userName, int pageNo, int pageSize) {
Page<RoleInfo> roles = rolePersistService.getRolesByUserName(userName, pageNo, pageSize);
if (roles == null) {
return new Page<>();
}
return roles;
}
public List<PermissionInfo> getPermissions(String role) {
List<PermissionInfo> permissionInfoList = permissionInfoMap.get(role);
if (!authConfigs.isCachingEnabled()) {
Page<PermissionInfo> permissionInfoPage = getPermissionsFromDatabase(role, DEFAULT_PAGE_NO,
Integer.MAX_VALUE);
if (permissionInfoPage != null) {
permissionInfoList = permissionInfoPage.getPageItems();
}
}
return permissionInfoList;
}
public Page<PermissionInfo> getPermissionsByRoleFromDatabase(String role, int pageNo, int pageSize) {
return permissionPersistService.getPermissions(role, pageNo, pageSize);
}
/**
* Add role.
* @param role role name
* @param username user name
*/
public void addRole(String role, String username) {
if (userDetailsService.getUserFromDatabase(username) == null) {
throw new IllegalArgumentException("user '" + username + "' not found!");
}
if (GLOBAL_ADMIN_ROLE.equals(role)) {
throw new IllegalArgumentException("role '" + GLOBAL_ADMIN_ROLE + "' is not permitted to create!");
}
rolePersistService.addRole(role, username);
roleSet.add(role);
}
public void deleteRole(String role, String userName) {
rolePersistService.deleteRole(role, userName);
}
public void deleteRole(String role) {
rolePersistService.deleteRole(role);
roleSet.remove(role);
}
public Page<PermissionInfo> getPermissionsFromDatabase(String role, int pageNo, int pageSize) {
Page<PermissionInfo> pageInfo = permissionPersistService.getPermissions(role, pageNo, pageSize);
if (pageInfo == null) {
return new Page<>();
}
return pageInfo;
}
/**
* Add permission.
* @param role role name
* @param resource resource
* @param action action
*/
public void addPermission(String role, String resource, String action) {
if (!roleSet.contains(role)) {
throw new IllegalArgumentException("role " + role + " not found!");
}
permissionPersistService.addPermission(role, resource, action);
}
public void deletePermission(String role, String resource, String action) {
permissionPersistService.deletePermission(role, resource, action);
}
public List<String> findRolesLikeRoleName(String role) {
return rolePersistService.findRolesLikeRoleName(role);
}
}

View File

@ -29,46 +29,47 @@ import java.util.Collection;
* @author wfnuser
*/
public class NacosUserDetails implements UserDetails {
private final User user;
public NacosUserDetails(User user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO: get authorities
return AuthorityUtils.commaSeparatedStringToAuthorityList("");
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
private final User user;
public NacosUserDetails(User user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO: get authorities
return AuthorityUtils.commaSeparatedStringToAuthorityList("");
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUsername();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}

View File

@ -40,76 +40,78 @@ import java.util.concurrent.ConcurrentHashMap;
*/
@Service
public class NacosUserDetailsServiceImpl implements UserDetailsService {
private Map<String, User> userMap = new ConcurrentHashMap<>();
@Autowired
private UserPersistService userPersistService;
@Autowired
private AuthConfigs authConfigs;
@Scheduled(initialDelay = 5000, fixedDelay = 15000)
private void reload() {
try {
Page<User> users = getUsersFromDatabase(1, Integer.MAX_VALUE);
if (users == null) {
return;
}
Map<String, User> map = new ConcurrentHashMap<>(16);
for (User user : users.getPageItems()) {
map.put(user.getUsername(), user);
}
userMap = map;
} catch (Exception e) {
Loggers.AUTH.warn("[LOAD-USERS] load failed", e);
}
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userMap.get(username);
if (!authConfigs.isCachingEnabled()) {
user = userPersistService.findUserByUsername(username);
}
if (user == null) {
throw new UsernameNotFoundException(username);
}
return new NacosUserDetails(user);
}
public void updateUserPassword(String username, String password) {
userPersistService.updateUserPassword(username, password);
}
public Page<User> getUsersFromDatabase(int pageNo, int pageSize) {
return userPersistService.getUsers(pageNo, pageSize);
}
public User getUser(String username) {
User user = userMap.get(username);
if (!authConfigs.isCachingEnabled()) {
user = getUserFromDatabase(username);
}
return user;
}
public User getUserFromDatabase(String username) {
return userPersistService.findUserByUsername(username);
}
public List<String> findUserLikeUsername(String username) {
return userPersistService.findUserLikeUsername(username);
}
private Map<String, User> userMap = new ConcurrentHashMap<>();
@Autowired
private UserPersistService userPersistService;
@Autowired
private AuthConfigs authConfigs;
@Scheduled(initialDelay = 5000, fixedDelay = 15000)
private void reload() {
try {
Page<User> users = getUsersFromDatabase(1, Integer.MAX_VALUE);
if (users == null) {
return;
}
Map<String, User> map = new ConcurrentHashMap<>(16);
for (User user : users.getPageItems()) {
map.put(user.getUsername(), user);
}
userMap = map;
}
catch (Exception e) {
Loggers.AUTH.warn("[LOAD-USERS] load failed", e);
}
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userMap.get(username);
if (!authConfigs.isCachingEnabled()) {
user = userPersistService.findUserByUsername(username);
}
if (user == null) {
throw new UsernameNotFoundException(username);
}
return new NacosUserDetails(user);
}
public void updateUserPassword(String username, String password) {
userPersistService.updateUserPassword(username, password);
}
public Page<User> getUsersFromDatabase(int pageNo, int pageSize) {
return userPersistService.getUsers(pageNo, pageSize);
}
public User getUser(String username) {
User user = userMap.get(username);
if (!authConfigs.isCachingEnabled()) {
user = getUserFromDatabase(username);
}
return user;
}
public User getUserFromDatabase(String username) {
return userPersistService.findUserByUsername(username);
}
public List<String> findUserLikeUsername(String username) {
return userPersistService.findUserLikeUsername(username);
}
public void createUser(String username, String password) {
userPersistService.createUser(username, password);
}
public void deleteUser(String username) {
userPersistService.deleteUser(username);
}
public void createUser(String username, String password) {
userPersistService.createUser(username, password);
}
public void deleteUser(String username) {
userPersistService.deleteUser(username);
}
}