Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SpringBoot身份验证数据源_Spring_Hibernate_Spring Security_Spring Boot_C3p0 - Fatal编程技术网

SpringBoot身份验证数据源

SpringBoot身份验证数据源,spring,hibernate,spring-security,spring-boot,c3p0,Spring,Hibernate,Spring Security,Spring Boot,C3p0,我在应用程序中使用SpringBoot、SpringSecurity、C3P0和JPA hibernate 如何让SpringBoot尝试使用与.properties文件中提供的数据源不同的数据源对用户进行身份验证 编辑1 public class AuthFilter extends AbstractAuthenticationProcessingFilter { private boolean postOnly = true; public AuthFilter() {

我在应用程序中使用SpringBoot、SpringSecurity、C3P0和JPA hibernate

如何让SpringBoot尝试使用与.properties文件中提供的数据源不同的数据源对用户进行身份验证

编辑1

public class AuthFilter extends AbstractAuthenticationProcessingFilter {
    private boolean postOnly = true;

    public AuthFilter() {
        super(new AntPathRequestMatcher("/login", "POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
            HttpServletResponse response) throws AuthenticationException {
        if (postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException(
                    "Authentication method not supported: "
                            + request.getMethod());
        }

        String email = request.getParameter("username");
        String password = request.getParameter("password");

        String username = email.substring(0, email.indexOf("@"));
        String db = email.substring(email.indexOf("@") + 1, email.lastIndexOf("."));

        if (username == null) {
            username = "";
        }

        if (password == null) {
            password = "";
        }

        username = username.trim();
        UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
                username, password);

        // Here I should change the DataSource before the authentication occurs.
        return this.getAuthenticationManager().authenticate(authRequest);
    }

    public void setPostOnly(boolean postOnly) {
        this.postOnly = postOnly;
    }
}
OP解决方案

我在我的
AuthenticationProvider
中为客户端创建了一个
sessionFactory
和一个数据源,并手动搜索他,而不是使用我的服务。成功了


如果您需要使用不同的系统,您可以使用ReST模板在自定义authenticationProvider中调用API。因此,通过ReST API,您可以进行身份验证。像这样的事情,

public static final String REST_SERVICE_URI = "<your microservice end 
  point>";
Users authApiObj = new Users();
authApiObj.username = "username";
authApiObj.password = "username";

RestTemplate restTemplate = new RestTemplate(); 
HttpEntity<Object> request = new HttpEntity<Object>(authApiObj, headers);
String responseString = restTemplate.postForObject(REST_SERVICE_URI, 
   request, String.class);
公共静态最终字符串REST_SERVICE_URI=”“;
Users authApiObj=新用户();
authApiObj.username=“username”;
authApiObj.password=“用户名”;
RestTemplate RestTemplate=新RestTemplate();
HttpEntity请求=新的HttpEntity(authApiObj,头文件);
String responseString=restTemplate.postForObject(REST\u服务\u URI,
请求,String.class);

否则,您需要配置spring cloud config server并启动您的spring boot应用程序(可选),并从已配置的spring config server访问应用程序中加载的动态属性;但可能会帮助其他人寻找答案(答案可能有点长)

注意:以下逻辑不会切换到同一请求中的多个DB源。JPA连接到
application.properties
文件中指向的主数据源。下面的逻辑只是使用JDBC模板进行额外的数据库连接

SpringBoot 2.0.1引入了一种可以根据请求动态使用适当数据源的方法。
datasource
的类型为
Map

本质上,数据源映射应该包含连接标识符作为键,数据源作为值。有两种方法可以填充地图

第1种方式:此处仅在应用程序启动时填充dataSourceMap。(假设所有用户都存在于不同的单个数据库中(主数据库除外),此方法就足够了。)

a。创建一个配置文件
ClientDataSourceConfig.java
,该文件在应用程序启动时加载,其中dataSourceMap是手动准备的,并为JPA设置默认目标DB源

ClientDataSourceConfig.java:

import com.company.tripmis.datasource.ClientDataSourceRouter;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ClientDataSourceConfig {

    @Value("${spring.datasource.driver}")
    private String driver;

    @Value("${spring.datasource.url}")
    private String url;

    @Value("${spring.datasource.username}")
    private String username;

    @Value("${spring.datasource.password}")
    private String password;

    public ClientDataSourceRouter dataSource;

    @Bean(name = "getDataSource") // <-- IMP: Bean and Returning manually created ClientDataSourceRouter
    public ClientDataSourceRouter getDataSource() throws Exception {
        dataSource = new ClientDataSourceRouter();

        // Here we are initialising default DB from application.properties file manually.

        dataSource.init(driver, url, username, password);
        return dataSource;
    }

}
第二种方法:为了动态更新dataSourceMap,创建一个过滤器,它将在每次请求时从DB读取数据,并更新相同的数据。(应使用相同的方法,以便不会在每次请求时命中DB,并定期更新CacheBucket。)

既然在应用程序启动时向datasourceMap添加了多个DB连接,那么我们需要做的就是在需要时使用
JDBCTemplate
连接进行用户身份验证

这可以通过使用过滤器或HttpInterceptor拦截HttpRequest来完成,也可以根据需要在
控制器
/
服务
层进行拦截

下面的代码在
过滤器
级别执行身份验证

import java.io.IOException;
import java.util.HashMap;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import com.company.tripmis.datasource.ClientDataSourceContext;
import com.company.tripmis.datasource.ClientDataSourceRouter;
import com.company.tripmis.model.pojo.ErrorModel;
import com.company.tripmis.model.pojo.ResponseModel;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

@Component
@Order(2)
public class RequestDataSourceFilter implements Filter {

    @Autowired
    private ApplicationContext applicationContext;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String companyId = httpRequest.getRequestURI().split("/")[1];

        ClientDataSourceRouter clientDataSourceRouterObj = (ClientDataSourceRouter) applicationContext
                .getBean("getDataSource");
        HashMap<Object, Object> dataSourcesMap = clientDataSourceRouterObj.getDataSources();
        // Some of the following code is for MultiTenant, if not needed, please ignore
        if (dataSourcesMap.get(companyId) == null) {
            ResponseModel responseModel = new ResponseModel();
            ErrorModel errorModel = new ErrorModel();
            errorModel.setCode("DB_RES_NOT_FND");
            errorModel.setMessage("The DB schema mapping not found for the given: " + companyId);
            responseModel.setSuccess(false);
            responseModel.setMessage("Requested DB resource not found");
            responseModel.setError(errorModel);
            ((HttpServletResponse) response).setHeader("Content-Type", "application/json");
            ((HttpServletResponse) response).setStatus(400);
            response.getOutputStream().write(new ObjectMapper().writeValueAsString(responseModel).getBytes());
            return;
        } else {
            String username = ""; // Read username from request
            JdbcTemplate jdbcTemplate = new JdbcTemplate((DataSource) dataSourcesMap.get(companyId));
            String sqlQuery = "select * from user where username = ?";
            // Prepare the query
            List<Model> userList = jdbcTemplate.query(sqlQuery, new Object[] { username },
                    new UserAuthMapper());
            // Replace with proper query and create a custom mapper as required.
            // And continue with the authentication here.
        }
        ClientDataSourceContext.setClientName(companyId);
        chain.doFilter(request, response);
    }
}
import java.io.IOException;
导入java.util.HashMap;
导入javax.servlet.Filter;
导入javax.servlet.FilterChain;
导入javax.servlet.ServletException;
导入javax.servlet.ServletRequest;
导入javax.servlet.ServletResponse;
导入javax.servlet.http.HttpServletRequest;
导入javax.servlet.http.HttpServletResponse;
导入javax.sql.DataSource;
导入com.company.tripmis.datasource.ClientDataSourceContext;
导入com.company.tripmis.datasource.clientdatasourceouter;
导入com.company.tripmis.model.pojo.ErrorModel;
导入com.company.tripmis.model.pojo.ResponseModel;
导入com.fasterxml.jackson.databind.ObjectMapper;
导入org.springframework.beans.factory.annotation.Autowired;
导入org.springframework.context.ApplicationContext;
导入org.springframework.core.annotation.Order;
导入org.springframework.jdbc.core.jdbc模板;
导入org.springframework.stereotype.Component;
@组成部分
@订单(2)
公共类RequestDataSourceFilter实现筛选器{
@自动连线
私有应用程序上下文应用程序上下文;
@凌驾
public void doFilter(ServletRequest请求、ServletResponse响应、FilterChain链)
抛出IOException、ServletException{
HttpServletRequest httpRequest=(HttpServletRequest)请求;
字符串companyId=httpRequest.getRequestURI().split(“/”[1];
ClientDataSourceRouter clientDataSourceRouterObj=(ClientDataSourceRouter)应用程序上下文
.getBean(“getDataSource”);
HashMap dataSourcesMap=clientDataSourceRouterObj.getDataSources();
//以下部分代码适用于多租户,如果不需要,请忽略
if(dataSourcesMap.get(companyId)==null){
ResponseModel ResponseModel=新的ResponseModel();
ErrorModel ErrorModel=新的ErrorModel();
errorModel.setCode(“DB_RES_NOT_FND”);
errorModel.setMessage(“找不到给定:“+companyId”)的DB架构映射);
responseModel.setSuccess(假);
setMessage(“未找到请求的数据库资源”);
responseModel.setError(errorModel);
setHeader(“内容类型”、“应用程序/json”);
((HttpServletResponse)响应);
response.getOutputStream().write(新的ObjectMapper().writeValueAsString(responseModel.getBytes());
返回;
}否则{
字符串username=”“;//从请求读取用户名
JdbcTemplate JdbcTemplate=newjdbctemplate((数据源)dataSourcesMap.get(companyId));
String sqlQuery=“select*from user where username=?”;
//准备查询
List userList=jdbcTemplate.query(sqlQuery,新对象[]{username},
新的UserAuthMapper());
//替换为正确的查询和cre
import java.io.IOException;
import java.util.HashMap;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import com.company.tripmis.datasource.ClientDataSourceContext;
import com.company.tripmis.datasource.ClientDataSourceRouter;
import com.company.tripmis.model.pojo.ErrorModel;
import com.company.tripmis.model.pojo.ResponseModel;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.Order;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

@Component
@Order(2)
public class RequestDataSourceFilter implements Filter {

    @Autowired
    private ApplicationContext applicationContext;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String companyId = httpRequest.getRequestURI().split("/")[1];

        ClientDataSourceRouter clientDataSourceRouterObj = (ClientDataSourceRouter) applicationContext
                .getBean("getDataSource");
        HashMap<Object, Object> dataSourcesMap = clientDataSourceRouterObj.getDataSources();
        // Some of the following code is for MultiTenant, if not needed, please ignore
        if (dataSourcesMap.get(companyId) == null) {
            ResponseModel responseModel = new ResponseModel();
            ErrorModel errorModel = new ErrorModel();
            errorModel.setCode("DB_RES_NOT_FND");
            errorModel.setMessage("The DB schema mapping not found for the given: " + companyId);
            responseModel.setSuccess(false);
            responseModel.setMessage("Requested DB resource not found");
            responseModel.setError(errorModel);
            ((HttpServletResponse) response).setHeader("Content-Type", "application/json");
            ((HttpServletResponse) response).setStatus(400);
            response.getOutputStream().write(new ObjectMapper().writeValueAsString(responseModel).getBytes());
            return;
        } else {
            String username = ""; // Read username from request
            JdbcTemplate jdbcTemplate = new JdbcTemplate((DataSource) dataSourcesMap.get(companyId));
            String sqlQuery = "select * from user where username = ?";
            // Prepare the query
            List<Model> userList = jdbcTemplate.query(sqlQuery, new Object[] { username },
                    new UserAuthMapper());
            // Replace with proper query and create a custom mapper as required.
            // And continue with the authentication here.
        }
        ClientDataSourceContext.setClientName(companyId);
        chain.doFilter(request, response);
    }
}