mirror of
https://gitee.com/log4j/pig.git
synced 2024-12-22 20:54:25 +08:00
commit
67d7490292
@ -27,7 +27,7 @@
|
||||
<description>nacos 注册配置中心</description>
|
||||
|
||||
<properties>
|
||||
<nacos.version>2.0.1.RELEASE</nacos.version>
|
||||
<nacos.version>2.0.2</nacos.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -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.addAllowedOriginPattern("*");
|
||||
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());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import com.alibaba.nacos.naming.controllers.OperatorController;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@ -36,76 +37,74 @@ 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 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 readiness(HttpServletRequest request) {
|
||||
boolean isConfigReadiness = isConfigReadiness();
|
||||
boolean isNamingReadiness = isNamingReadiness(request);
|
||||
|
||||
if (isConfigReadiness && isNamingReadiness) {
|
||||
return ResponseEntity.ok().body("OK");
|
||||
}
|
||||
|
||||
if (!isConfigReadiness && !isNamingReadiness) {
|
||||
return ResponseEntity.status(500).body("Config and Naming are not in readiness");
|
||||
}
|
||||
|
||||
if (!isConfigReadiness) {
|
||||
return ResponseEntity.status(500).body("Config is not in readiness");
|
||||
}
|
||||
|
||||
return ResponseEntity.status(500).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;
|
||||
}
|
||||
}
|
||||
|
@ -19,20 +19,16 @@ package com.alibaba.nacos.controller;
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.common.ActionTypes;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.model.RestResultUtils;
|
||||
import com.alibaba.nacos.config.server.model.TenantInfo;
|
||||
import com.alibaba.nacos.config.server.service.repository.PersistService;
|
||||
import com.alibaba.nacos.enums.NamespaceTypeEnum;
|
||||
import com.alibaba.nacos.model.Namespace;
|
||||
import com.alibaba.nacos.model.NamespaceAllInfo;
|
||||
import com.alibaba.nacos.security.nacos.NacosAuthConfig;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@ -57,58 +53,72 @@ public class NamespaceController {
|
||||
|
||||
private static final int NAMESPACE_ID_MAX_LENGTH = 128;
|
||||
|
||||
private static final String DEFAULT_NAMESPACE = "public";
|
||||
|
||||
private static final int DEFAULT_QUOTA = 200;
|
||||
|
||||
private static final String DEFAULT_CREATE_SOURCE = "nacos";
|
||||
|
||||
private static final String DEFAULT_NAMESPACE_SHOW_NAME = "Public";
|
||||
|
||||
private static final String DEFAULT_NAMESPACE_DESCRIPTION = "Public Namespace";
|
||||
|
||||
private static final String DEFAULT_TENANT = "";
|
||||
|
||||
private static final String DEFAULT_KP = "1";
|
||||
|
||||
/**
|
||||
* Get namespace list.
|
||||
* @param request request
|
||||
*
|
||||
* @param request request
|
||||
* @param response response
|
||||
* @return namespace list
|
||||
*/
|
||||
@GetMapping
|
||||
public RestResult<List<Namespace>> getNamespaces(HttpServletRequest request, HttpServletResponse response) {
|
||||
RestResult<List<Namespace>> rr = new RestResult<List<Namespace>>();
|
||||
rr.setCode(200);
|
||||
// TODO 获取用kp
|
||||
List<TenantInfo> tenantInfos = persistService.findTenantByKp("1");
|
||||
Namespace namespace0 = new Namespace("", "public", 200, persistService.configInfoCount(""), 0);
|
||||
List<TenantInfo> tenantInfos = persistService.findTenantByKp(DEFAULT_KP);
|
||||
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) {
|
||||
int configCount = persistService.configInfoCount(tenantInfo.getTenantId());
|
||||
Namespace namespaceTmp = new Namespace(tenantInfo.getTenantId(), tenantInfo.getTenantName(), 200,
|
||||
configCount, 2);
|
||||
Namespace namespaceTmp = new Namespace(tenantInfo.getTenantId(), tenantInfo.getTenantName(), DEFAULT_QUOTA,
|
||||
configCount, NamespaceTypeEnum.CUSTOM.getType());
|
||||
namespaces.add(namespaceTmp);
|
||||
}
|
||||
rr.setData(namespaces);
|
||||
return rr;
|
||||
return RestResultUtils.success(namespaces);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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, "Public", 200, persistService.configInfoCount(""), 0,
|
||||
"Public Namespace");
|
||||
}
|
||||
else {
|
||||
TenantInfo tenantInfo = persistService.findTenantByKp("1", namespaceId);
|
||||
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(), 200, configCount, 2,
|
||||
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
|
||||
@ -116,13 +126,12 @@ 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;
|
||||
@ -134,13 +143,14 @@ public class NamespaceController {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
persistService.insertTenantInfoAtomic("1", namespaceId, namespaceName, namespaceDesc, "nacos",
|
||||
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
|
||||
*/
|
||||
@ -154,33 +164,35 @@ 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("1", namespace, namespaceShowName, namespaceDesc);
|
||||
persistService.updateTenantNameAtomic(DEFAULT_KP, namespace, namespaceShowName, namespaceDesc);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
persistService.removeTenantInfoAtomic("1", namespaceId);
|
||||
@RequestParam("namespaceId") String namespaceId) {
|
||||
persistService.removeTenantInfoAtomic(DEFAULT_KP, namespaceId);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@ package com.alibaba.nacos.controller;
|
||||
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.common.ActionTypes;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.model.RestResultUtils;
|
||||
import com.alibaba.nacos.security.nacos.NacosAuthConfig;
|
||||
import com.alibaba.nacos.security.nacos.roles.NacosRoleServiceImpl;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -39,51 +39,53 @@ 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 new RestResult<>(200, "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 new RestResult<>(200, "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!");
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ package com.alibaba.nacos.controller;
|
||||
|
||||
import com.alibaba.nacos.auth.annotation.Secured;
|
||||
import com.alibaba.nacos.auth.common.ActionTypes;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.model.RestResultUtils;
|
||||
import com.alibaba.nacos.security.nacos.NacosAuthConfig;
|
||||
import com.alibaba.nacos.security.nacos.roles.NacosRoleServiceImpl;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -41,69 +41,70 @@ 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 new RestResult<>(200, "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 new RestResult<>(200, "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!");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -34,21 +34,22 @@ 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 serverState() {
|
||||
Map<String, String> serverState = new HashMap<>(3);
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import com.alibaba.nacos.auth.common.AuthConfigs;
|
||||
import com.alibaba.nacos.auth.common.AuthSystemTypes;
|
||||
import com.alibaba.nacos.auth.exception.AccessException;
|
||||
import com.alibaba.nacos.common.model.RestResult;
|
||||
import com.alibaba.nacos.common.model.RestResultUtils;
|
||||
import com.alibaba.nacos.common.utils.JacksonUtils;
|
||||
import com.alibaba.nacos.common.utils.Objects;
|
||||
import com.alibaba.nacos.config.server.auth.RoleInfo;
|
||||
@ -37,6 +38,7 @@ import com.alibaba.nacos.security.nacos.users.NacosUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.utils.PasswordEncoderUtil;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
@ -63,229 +65,218 @@ 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!");
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private JwtTokenManager jwtTokenManager;
|
||||
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 AuthenticationManager authenticationManager;
|
||||
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 NacosUserDetailsServiceImpl userDetailsService;
|
||||
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 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 new RestResult<>(200, "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 new RestResult<>(200, "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 new RestResult<>(200, "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();
|
||||
// JSONObject result = new JSONObject();
|
||||
result.put(Constants.ACCESS_TOKEN, user.getToken());
|
||||
result.put(Constants.TOKEN_TTL, authConfigs.getTokenValidityInSeconds());
|
||||
result.put(Constants.GLOBAL_ADMIN, user.isGlobalAdmin());
|
||||
return result;
|
||||
}
|
||||
|
||||
// 通过用户名和密码创建一个 Authentication 认证对象,实现类为 UsernamePasswordAuthenticationToken
|
||||
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username,
|
||||
password);
|
||||
|
||||
RestResult<String> rr = new RestResult<String>();
|
||||
try {
|
||||
// 通过 AuthenticationManager(默认实现为ProviderManager)的authenticate方法验证
|
||||
// Authentication 对象
|
||||
Authentication authentication = authenticationManager.authenticate(authenticationToken);
|
||||
// 将 Authentication 绑定到 SecurityContext
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
// 生成Token
|
||||
String token = jwtTokenManager.createToken(authentication);
|
||||
// 将Token写入到Http头部
|
||||
response.addHeader(NacosAuthConfig.AUTHORIZATION_HEADER, "Bearer " + token);
|
||||
rr.setCode(200);
|
||||
rr.setData("Bearer " + token);
|
||||
return rr;
|
||||
}
|
||||
catch (BadCredentialsException authentication) {
|
||||
rr.setCode(401);
|
||||
rr.setMessage("Login failed");
|
||||
return rr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
|
||||
RestResult<String> rr = new RestResult<String>();
|
||||
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));
|
||||
rr.setCode(200);
|
||||
rr.setMessage("Update password success");
|
||||
}
|
||||
else {
|
||||
rr.setCode(401);
|
||||
rr.setMessage("Old password is invalid");
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
rr.setCode(500);
|
||||
rr.setMessage("Update userpassword failed");
|
||||
}
|
||||
return rr;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 1999-2021 Alibaba Group Holding Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.nacos.enums;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
@ -36,42 +36,41 @@ 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(7);
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
* 0 : Global configuration, 1 : Default private namespace ,2 : Custom namespace.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -40,60 +40,64 @@ 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ import java.util.List;
|
||||
|
||||
import static com.alibaba.nacos.security.nacos.roles.NacosRoleServiceImpl.GLOBAL_ADMIN_ROLE;
|
||||
|
||||
|
||||
/**
|
||||
* LDAP auth provider.
|
||||
*
|
||||
@ -52,118 +53,114 @@ 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_";
|
||||
|
||||
@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.isNotEmpty(roleInfos)) {
|
||||
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, "simple");
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,101 +44,95 @@ 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 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";
|
||||
|
||||
@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 = "/**";
|
||||
}
|
||||
else if (AuthSystemTypes.LDAP.name().equalsIgnoreCase(authConfigs.getNacosAuthSystemType())) {
|
||||
ignoreUrls = "/**";
|
||||
}
|
||||
if (StringUtils.isBlank(authConfigs.getNacosAuthSystemType())) {
|
||||
ignoreUrls = env.getProperty("nacos.security.ignore.urls", "/**");
|
||||
}
|
||||
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();
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,9 +24,9 @@ import com.alibaba.nacos.auth.model.Permission;
|
||||
import com.alibaba.nacos.auth.model.User;
|
||||
import com.alibaba.nacos.config.server.auth.RoleInfo;
|
||||
import com.alibaba.nacos.config.server.utils.RequestUtil;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import com.alibaba.nacos.security.nacos.roles.NacosRoleServiceImpl;
|
||||
import com.alibaba.nacos.security.nacos.users.NacosUser;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import io.jsonwebtoken.ExpiredJwtException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -48,160 +48,157 @@ import java.util.List;
|
||||
*/
|
||||
@Component
|
||||
public class NacosAuthManager implements AuthManager {
|
||||
|
||||
private static final String TOKEN_PREFIX = "Bearer ";
|
||||
|
||||
@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("username");
|
||||
String password = request.getParameter("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("username");
|
||||
String password = request.getHeader("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);
|
||||
}
|
||||
}
|
||||
|
@ -23,9 +23,9 @@ import com.alibaba.nacos.config.server.auth.PermissionPersistService;
|
||||
import com.alibaba.nacos.config.server.auth.RoleInfo;
|
||||
import com.alibaba.nacos.config.server.auth.RolePersistService;
|
||||
import com.alibaba.nacos.config.server.model.Page;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import com.alibaba.nacos.security.nacos.NacosAuthConfig;
|
||||
import com.alibaba.nacos.security.nacos.users.NacosUserDetailsServiceImpl;
|
||||
import com.alibaba.nacos.core.utils.Loggers;
|
||||
import io.jsonwebtoken.lang.Collections;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.mina.util.ConcurrentHashSet;
|
||||
@ -49,198 +49,200 @@ 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;
|
||||
}
|
||||
|
||||
public static final String GLOBAL_ADMIN_ROLE = "ROLE_ADMIN";
|
||||
|
||||
@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, 1,
|
||||
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, 1,
|
||||
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, 1, 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, 1, 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -29,47 +29,46 @@ 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;
|
||||
}
|
||||
}
|
||||
|
@ -40,78 +40,76 @@ 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);
|
||||
}
|
||||
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
pom.xml
2
pom.xml
@ -47,7 +47,7 @@
|
||||
<captcha.version>2.2.0</captcha.version>
|
||||
<velocity.version>1.7</velocity.version>
|
||||
<configuration.version>1.10</configuration.version>
|
||||
<nacos.version>2.0.1</nacos.version>
|
||||
<nacos.version>2.0.2</nacos.version>
|
||||
<jasypt.version>2.1.0</jasypt.version>
|
||||
<swagger.fox.version>3.0.0</swagger.fox.version>
|
||||
<xxl-job.version>2.3.0</xxl-job.version>
|
||||
|
Loading…
Reference in New Issue
Block a user