我正在尝试在春季实现多租户。我使用 JWT,并且我将tenant_id 存储在JWT 中,我已配置我的类MultiTenantDataSourceRouter 扩展AbstractRoutingDataSource 以使查找键为tenant_id。
@Override
protected Object determineCurrentLookupKey() {
var authentication = SecurityContextHolder.getContext().getAuthentication();
if(authentication!= null && authentication.getPrincipal() instanceof User user) {
return user.getTenant_id();
}
return null;
}
我还有一个以用户身份登录的控制器方法。登录后,我想创建一个用户对象并将其存储在该租户特有的数据库中
public ResponseEntity<AuthenticationResponse> loginUser(AuthenticateRequest authenticateRequest) {
//authenticate the User
authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(authenticateRequest.getEmail(),authenticateRequest.getPassword()));
//this line of code runs oly if authentication is successful
User user = userRepository.findByEmail(authenticateRequest.getEmail()).orElseThrow();
String jwt = jwtService.generateToken(user);
//set the security context to allow routing of db and to know the tenantID and also set the datasource
SecurityContextHolder.getContext()
.setAuthentication(new UsernamePasswordAuthenticationToken(user.getUsername(),null,user.getAuthorities()));
var mds = new MultiTenantDataSourceRouter();
mds.setTargetDataSources(dataSourceConfig.loadAllDataSources());
mds.afterPropertiesSet();
//create an Employee Object for the user once
Employee employee = employeeRepository.findByEmail(user.getEmail());
if(employee!= null){
Employee newEmployee = Employee.builder()
.email(user.getEmail())
.name(user.getName())
.build();
}
return ResponseEntity.ok().body(new AuthenticationResponse(jwt));
}
应用程序启动时,我已加载数据源(dataSourceConfig.loadAllDataSources())这是一个返回tenant_id的Map和相应数据源的bean。但是当我调用此方法时,默认数据源通过app加载到应用程序中.properties 是查找 findbyEmail() 方法的员工对象的位置。我希望它在与该用户关联的租户内查找它,但它没有
这会导致错误,因为我的默认数据库没有员工表。
我相信您错过了一个步骤,告诉您的应用程序需要为您的员工使用哪个租户。您使用 dataSourceConfig.loadAllDataSources() 为多租户数据源提供一些数据源,但您没有告诉它使用哪一个,因此它使用默认的数据源。