• spring 配置 Http请求账号密码验证功能


    HttpRequester 类有构造方法,通过构造方法,加载http请求的参数。

    public HttpRequester(int connectionRequestTimeout, int connectionTimeout, int socketTimeout, String 	defaultCharset, String proxyServer,HttpClientContext httpClientContext) {
    	super();
    	init(connectionRequestTimeout, connectionTimeout, socketTimeout, defaultCharset, proxyServer,httpClientContext);
    }
    
    private void init(
    		   int connectionRequestTimeout ,int connectionTimeout ,int socketTimeout
    		 , String defaultCharset ,String proxyServer , HttpClientContext httpClientContext
    ){
    	this.httpClient = HttpClients.createDefault();
    
    	Builder requestBuilder = RequestConfig.custom();
    	requestBuilder.setConnectionRequestTimeout(connectionRequestTimeout);
    	requestBuilder.setConnectTimeout(connectionTimeout);
    	requestBuilder.setSocketTimeout(socketTimeout);
    	if (StringUtils.isNotBlank(proxyServer)) {
    		requestBuilder.setProxy(HttpHost.create(proxyServer));
    	}
    	this.requestConfig = requestBuilder.build();
    	this.responseHandler = new DefaultResponseHandler(Charset.forName(defaultCharset));
    	this.httpClientContext = httpClientContext;
    }
    

    其中,需要有验证用户账号密码的代码,JAVA代码如下:

    UsernamePasswordCredentials usernamePasswordCredentials = new UsernamePasswordCredentials("XXX", "123456");
    CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    credentialsProvider.setCredentials(new AuthScope(AuthScope.ANY_HOST,AuthScope.ANY_PORT),usernamePasswordCredentials);
    	
    HttpClientContext httpClientContext = HttpClientContext.create();
    httpClientContext.setCredentialsProvider(credentialsProvider);
    

    以上JAVA代码,用spring配置bean方式实现。

    此时,spring 配置构造方法为:

    <bean id="httpRequester" class="com.champion.common.util.http.HttpRequester">
    	<constructor-arg value="${httpRequester.connectionRequestTimeout}" type="int" />
    	<constructor-arg value="${httpRequester.connectionTimeout}" type="int" />
    	<constructor-arg value="${httpRequester.socketTimeout}" type="int" />
    	<constructor-arg type="String" value="UTF-8" />
    	<constructor-arg type="String"><null/></constructor-arg>
    	<constructor-arg type="org.apache.http.client.protocol.HttpClientContext">
    		<!-- 待完善 -->
    	</constructor-arg>
    </bean>
    

    注:

    1. type为String时,可以省略不写。
    2. 配置参数数量要与构造函数的参数数量保持一致(构造函数有多个,不同数量对应不同构造函数,因此可以写多个配置,通过id来区分不同的配置的JAVA类)。
    3. <null/>表示为空值。
    4. Spring通过构造方法注入的四种方式
      1. 第一种方法:根据索引赋值,索引都是以0开头的:

         <constructor-arg index="0" value="3500" />
        
      2. 第二种方法:根据所属类型传值(根据顺序排的)

         <constructor-arg type="java.lang.Double" value="3500" />
        
      3. 第三种方法:根据参数的名字传值

         <constructor-arg name="salary" value="3500" />
        
      4. 第四种方法:直接传值(根据顺序排的)

         <constructor-arg  value="3500" />
        

    继续:
    查看类HttpClientContext,有工厂方法create,创建HttpClientContext对象

    public static HttpClientContext adapt(final HttpContext context) {
        if (context instanceof HttpClientContext) {
            return (HttpClientContext) context;
        } else {
            return new HttpClientContext(context);
        }
    }
    
    public static HttpClientContext create() {
        return new HttpClientContext(new BasicHttpContext());
    }
    
    public HttpClientContext(final HttpContext context) {
        super(context);
    }
    
    public HttpClientContext() {
        super();
    }
    

    然后配置更新如下:

    <bean id="httpRequester" class="com.champion.common.util.http.HttpRequester">
    	<constructor-arg value="${httpRequester.connectionRequestTimeout}" type="int" />
    	<constructor-arg value="${httpRequester.connectionTimeout}" type="int" />
    	<constructor-arg value="${httpRequester.socketTimeout}" type="int" />
    	<constructor-arg type="String" value="UTF-8" />
    	<constructor-arg type="String"><null/></constructor-arg>
    	<constructor-arg type="org.apache.http.client.protocol.HttpClientContext">
    		<bean class="org.apache.http.client.protocol.HttpClientContext" factory-method="create">
    			<!-- 待完善 -->
    		</bean>
    	</constructor-arg>
    </bean>
    

    继续,查看JAVA代码如下:

    HttpClientContext httpClientContext = HttpClientContext.create();
    httpClientContext.setCredentialsProvider(credentialsProvider);
    

    需要有credentialsProvider参数,该参数在HttpClientContext里面可以通过get set获取,代码如下:

    public CredentialsProvider getCredentialsProvider() {
        return getAttribute(CREDS_PROVIDER, CredentialsProvider.class);
    }
    
    public void setCredentialsProvider(final CredentialsProvider credentialsProvider) {
        setAttribute(CREDS_PROVIDER, credentialsProvider);
    }
    

    然后配置更新如下:

    <bean id="httpRequester" class="com.champion.common.util.http.HttpRequester">
    	<constructor-arg value="${httpRequester.connectionRequestTimeout}" type="int" />
    	<constructor-arg value="${httpRequester.connectionTimeout}" type="int" />
    	<constructor-arg value="${httpRequester.socketTimeout}" type="int" />
    	<constructor-arg type="String" value="UTF-8" />
    	<constructor-arg type="String"><null/></constructor-arg>
    	<constructor-arg type="org.apache.http.client.protocol.HttpClientContext">
    		<bean class="org.apache.http.client.protocol.HttpClientContext" factory-method="create">
    			<property name="credentialsProvider">
    				<!-- 待完善 -->
    			</property>
    		</bean>
    	</constructor-arg>
    </bean>
    

    继续,查看JAVA代码如下:

    CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    

    继续,查看BasicCredentialsProvider如下:

    public class BasicCredentialsProvider implements CredentialsProvider {
    
    private final ConcurrentHashMap<AuthScope, Credentials> credMap;
    
    
    public BasicCredentialsProvider() {
        super();
        this.credMap = new ConcurrentHashMap<AuthScope, Credentials>();
    }
    
    @Override
    public void setCredentials(
            final AuthScope authscope,
            final Credentials credentials) {
        Args.notNull(authscope, "Authentication scope");
        credMap.put(authscope, credentials);
    }
    
    
    private static Credentials matchCredentials(
            final Map<AuthScope, Credentials> map,
            final AuthScope authscope) {
        // see if we get a direct hit
        Credentials creds = map.get(authscope);
        if (creds == null) {
            // Nope.
            // Do a full scan
            int bestMatchFactor  = -1;
            AuthScope bestMatch  = null;
            for (final AuthScope current: map.keySet()) {
                final int factor = authscope.match(current);
                if (factor > bestMatchFactor) {
                    bestMatchFactor = factor;
                    bestMatch = current;
                }
            }
            if (bestMatch != null) {
                creds = map.get(bestMatch);
            }
        }
        return creds;
    }
    
    @Override
    public Credentials getCredentials(final AuthScope authscope) {
        Args.notNull(authscope, "Authentication scope");
        return matchCredentials(this.credMap, authscope);
    }
    

    发现无法通过get set或者构造方式等方式加载credentialsProvider。

    因此,新建JAVA类,代码如下(可以通过工厂方式注入该bean):

    public class CredentialsProviders {
    	public final static CredentialsProvider createUsernamePasswordCredentialsProvider(String username, String password,String authScopeHost,int authScopePort) {
    		UsernamePasswordCredentials usernamePasswordCredentials = new UsernamePasswordCredentials(username, password);
    		CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    		if(StringUtils.isBlank(authScopeHost)){
    			authScopeHost = AuthScope.ANY_HOST;
    		}
    		if(authScopePort < 0){
    			authScopePort = AuthScope.ANY_PORT;
    		}
    		credentialsProvider.setCredentials(new AuthScope(authScopeHost,authScopePort),
    				usernamePasswordCredentials);
    		return credentialsProvider;
    	}
    	public final static CredentialsProvider createUsernamePasswordCredentialsProvider(String username, String password) {
    		return createUsernamePasswordCredentialsProvider(username, password,AuthScope.ANY_HOST,AuthScope.ANY_PORT);
    	}
    }
    

    然后配置更新如下:

    <bean id="httpRequester" class="com.champion.common.util.http.HttpRequester">
    	<constructor-arg value="${httpRequester.connectionRequestTimeout}" type="int" />
    	<constructor-arg value="${httpRequester.connectionTimeout}" type="int" />
    	<constructor-arg value="${httpRequester.socketTimeout}" type="int" />
    	<constructor-arg type="String" value="UTF-8" />
    	<constructor-arg type="String"><null/></constructor-arg>
    	<constructor-arg type="org.apache.http.client.protocol.HttpClientContext">
    		<bean class="org.apache.http.client.protocol.HttpClientContext" factory-method="create">
    			<property name="credentialsProvider">
    				<bean class="com.champion.common.util.http.CredentialsProviders"
    					factory-method="createUsernamePasswordCredentialsProvider">
    					<constructor-arg value="${svn.username}" />
    					<constructor-arg value="${svn.password}" />
    				</bean>
    			</property>
    		</bean>
    	</constructor-arg>
    </bean>
    

    自此,通过spring配置实现用户账号密码验证http请求的功能已经实现。

    延伸阅读:
    spring四种依赖注入方式
    Spring通过构造方法注入的四种方式

  • 相关阅读:
    tomcat页面跳转问题
    linux shell脚本攻略总结
    nginx中配置tomcat
    centos中文输入法支持
    esxi创建centos系统
    linux日常总结
    你不知道的编码软件排行榜
    Beyond Compare切换比较会话过滤模式的方法
    用Beyond Compare找代码bug的方法
    文件对比工具比较表格时怎么显示行号
  • 原文地址:https://www.cnblogs.com/cuiyf/p/6912254.html
Copyright © 2020-2023  润新知