提交 2cc97b1d 编写于 作者: 智布道's avatar 智布道 👁

📝 change: Optimize code

上级 7ca2d805
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>jap</artifactId>
<groupId>com.fujieid</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jap-http-api</artifactId>
<version>1.0.2</version>
<parent>
<artifactId>jap</artifactId>
<groupId>com.fujieid</groupId>
<version>${revision}</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jap-http-api</artifactId>
<version>1.0.2</version>
<description>jap-http-api</description>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.fujieid</groupId>
<artifactId>jap-core</artifactId>
</dependency>
<dependency>
<groupId>me.zhyd.oauth</groupId>
<artifactId>JustAuth</artifactId>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>com.fujieid</groupId>
<artifactId>jap-core</artifactId>
</dependency>
<dependency>
<groupId>com.xkcoding.http</groupId>
<artifactId>simple-http</artifactId>
</dependency>
</dependencies>
</project>
......@@ -8,20 +8,18 @@ import com.fujieid.jap.httpapi.enums.ForBearerTokenEnum;
import com.fujieid.jap.httpapi.enums.HttpMethodEnum;
import com.fujieid.jap.httpapi.strategy.GetTokenFromResponseStrategy;
import com.fujieid.jap.httpapi.strategy.RequestBodyToJapUserStrategy;
import com.fujieid.jap.httpapi.util.SimpleAuthJsonUtil;
import com.xkcoding.json.JsonUtil;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.util.HashMap;
import java.util.Map;
/**
* Configuration file for http api authorization module
* Configuration file for http api authorization module
*
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @since 1.0.5
*/
public class HttpApiConfig extends AuthenticateConfig {
......@@ -48,17 +46,17 @@ public class HttpApiConfig extends AuthenticateConfig {
/**
* custom headers will be carried when request third-party system.
*/
private Map<String,String> customHeaders;
private Map<String, String> customHeaders;
/**
* custom params will be carried when request third-party system.
*/
private Map<String,String> customParams;
private Map<String, String> customParams;
/**
* custom body will be carried when request third-party system in json format.
*/
private Map<String,String> customBody;
private Map<String, String> customBody;
/**
* define this field when authSchema is BEARER
......@@ -68,22 +66,19 @@ public class HttpApiConfig extends AuthenticateConfig {
/**
* if user auth info field is "body", by default, analyze user auth info by json format. ex:
* {
* "username":"admin",
* "password":"123456"
* "username":"admin",
* "password":"123456"
* }
* Developer's system should customize requestBodyToJapUserStrategy to get userinfo form request if user auth info is not this format.
*/
private RequestBodyToJapUserStrategy requestBodyToJapUserStrategy = new RequestBodyToJapUserStrategy(){
@Override
public JapUser decode(HttpServletRequest request) throws Exception {
BufferedReader reader = request.getReader();
StringBuilder body = new StringBuilder();
String str = null;
while ((str = reader.readLine()) != null) {
body.append(str);
}
return JsonUtil.toBean(body.toString(),JapUser.class);
private RequestBodyToJapUserStrategy requestBodyToJapUserStrategy = request -> {
BufferedReader reader = request.getReader();
StringBuilder body = new StringBuilder();
String str = null;
while ((str = reader.readLine()) != null) {
body.append(str);
}
return JsonUtil.toBean(body.toString(), JapUser.class);
};
/**
......@@ -99,25 +94,22 @@ public class HttpApiConfig extends AuthenticateConfig {
* Use this strategy to extract the token from response body.
* By default, search for field like "token":"xxxxxxxx" in response.
*/
private GetTokenFromResponseStrategy getTokenFromResponseStrategy = new GetTokenFromResponseStrategy() {
@Override
public String getToken(String body) {
try{
int i1 = body.indexOf("\"token\"")+7;
int i2 = body.indexOf(':', i1);
int i3 = body.indexOf("\"",i2)+1;
int i4 = body.indexOf("\"", i3+1);
return body.substring(i3,i4);
}catch (Exception e){
return null;
}
private GetTokenFromResponseStrategy getTokenFromResponseStrategy = body -> {
try {
int i1 = body.indexOf("\"token\"") + 7;
int i2 = body.indexOf(':', i1);
int i3 = body.indexOf("\"", i2) + 1;
int i4 = body.indexOf("\"", i3 + 1);
return body.substring(i3, i4);
} catch (Exception e) {
return null;
}
};
public HttpApiConfig() {
}
public HttpApiConfig(HttpApiConfig httpApiConfig,String loginUrl) {
public HttpApiConfig(HttpApiConfig httpApiConfig, String loginUrl) {
this.authSchema = httpApiConfig.authSchema;
this.httpMethod = httpApiConfig.httpMethod;
this.loginUrl = loginUrl;
......@@ -189,15 +181,15 @@ public class HttpApiConfig extends AuthenticateConfig {
return customParams;
}
public Map<String, Object> getCustomParamsObjects() {
return new HashMap<>(customParams);
}
public HttpApiConfig setCustomParams(Map<String, String> customParams) {
this.customParams = customParams;
return this;
}
public Map<String, Object> getCustomParamsObjects() {
return new HashMap<>(customParams);
}
public Map<String, String> getCustomBody() {
return customBody;
}
......
package com.fujieid.jap.httpapi;
import cn.hutool.core.codec.Base64;
import com.fujieid.jap.core.JapUser;
import com.fujieid.jap.core.JapUserService;
import com.fujieid.jap.core.cache.JapCache;
......@@ -9,22 +10,21 @@ import com.fujieid.jap.core.exception.JapException;
import com.fujieid.jap.core.result.JapErrorCode;
import com.fujieid.jap.core.result.JapResponse;
import com.fujieid.jap.core.strategy.AbstractJapStrategy;
import com.fujieid.jap.http.JapHttpRequest;
import com.fujieid.jap.http.JapHttpResponse;
import com.fujieid.jap.httpapi.enums.AuthSchemaEnum;
import com.fujieid.jap.httpapi.enums.HttpMethodEnum;
import com.fujieid.jap.httpapi.subject.DigestAuthorizationSubject;
import com.fujieid.jap.httpapi.subject.DigestWwwAuthenticateSubject;
import com.fujieid.jap.httpapi.subject.HttpAuthResponse;
import com.fujieid.jap.httpapi.util.*;
import me.zhyd.oauth.utils.Base64Utils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* The strategy for jap-http-api module to request third party system.
*
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @since 1.0.5
*/
public class HttpApiStrategy extends AbstractJapStrategy {
......@@ -34,7 +34,7 @@ public class HttpApiStrategy extends AbstractJapStrategy {
}
@Override
public JapResponse authenticate(AuthenticateConfig config, HttpServletRequest request, HttpServletResponse response) {
public JapResponse authenticate(AuthenticateConfig config, JapHttpRequest request, JapHttpResponse response) {
try {
checkAuthenticateConfig(config, HttpApiConfig.class);
} catch (JapException e) {
......@@ -46,39 +46,39 @@ public class HttpApiStrategy extends AbstractJapStrategy {
return this.doAuthenticate(httpApiConfig, request, response);
}
private JapResponse doAuthenticate(HttpApiConfig config, HttpServletRequest servletRequest, HttpServletResponse servletResponse) {
private JapResponse doAuthenticate(HttpApiConfig config, JapHttpRequest request, JapHttpResponse response) {
HttpAuthResponse authResponse = null;
JapUser japUser = null;
try {
japUser = getJapUser(servletRequest, config);
japUser = getJapUser(request, config);
if (japUser == null) {
return JapResponse.error(JapErrorCode.MISS_CREDENTIALS);
}
switch (config.getAuthSchema()) {
case basic:
authResponse = doBasicAuth(japUser, config, servletResponse);
case BASIC:
authResponse = doBasicAuth(japUser, config, response);
break;
case digest:
authResponse = doDigestAuth(japUser,config,servletResponse);
case DIGEST:
authResponse = doDigestAuth(japUser, config, response);
break;
case bearer:
authResponse = doBearerAuth(japUser,config,servletResponse);
case BEARER:
authResponse = doBearerAuth(japUser, config, response);
break;
default:
break;
}
}catch (JapException e){
return JapResponse.error(e.getErrorCode(),e.getErrorMessage());
} catch (JapException e) {
return JapResponse.error(e.getErrorCode(), e.getErrorMessage());
} catch (Exception e) {
e.printStackTrace();
}
if (authResponse!=null&&authResponse.isSuccess()) {
if(config.getAuthSchema()== AuthSchemaEnum.basic||config.getAuthSchema()==AuthSchemaEnum.digest){
if (authResponse != null && authResponse.isSuccess()) {
if (config.getAuthSchema() == AuthSchemaEnum.BASIC || config.getAuthSchema() == AuthSchemaEnum.DIGEST) {
japUserService.createAndGetHttpApiUser(japUser);
}
return JapResponse.success(authResponse.getBody());
......@@ -87,19 +87,19 @@ public class HttpApiStrategy extends AbstractJapStrategy {
}
}
private HttpAuthResponse doDigestAuth(JapUser japUser, HttpApiConfig config, HttpServletResponse servletResponse) {
private HttpAuthResponse doDigestAuth(JapUser japUser, HttpApiConfig config, JapHttpResponse response) {
/*
* send a request to third-party server to get a random number and encryption algorithm
* see: https://datatracker.ietf.org/doc/html/rfc2069#section-2.1.1
*/
HttpAuthResponse responseForWWWAuth = HttpAuthUtil.sendRequest(config.getLoginUrl(),
HttpMethodEnum.get,
config.getCustomHeaders(),
config.getCustomParams(),
SimpleAuthJsonUtil.getJsonStrByParams(config.getCustomBody()));
HttpAuthResponse responseForWWWAuth = HttpAuthUtil.sendRequest(config.getLoginUrl(),
HttpMethodEnum.GET,
config.getCustomHeaders(),
config.getCustomParams(),
SimpleAuthJsonUtil.getJsonStrByParams(config.getCustomBody()));
if(responseForWWWAuth==null||responseForWWWAuth.getHeaders()==null){
if (responseForWWWAuth == null || responseForWWWAuth.getHeaders() == null) {
return null;
}
HttpAuthResponse result = null;
......@@ -107,7 +107,7 @@ public class HttpApiStrategy extends AbstractJapStrategy {
try {
wwwAuthenticate = responseForWWWAuth.getHeaders().get("WWW-Authenticate").get(0).replaceFirst("Digest ", "");
DigestWwwAuthenticateSubject wwwAuthenticateSubject = (DigestWwwAuthenticateSubject) SubjectSerializeUtil.deSerialize(DigestWwwAuthenticateSubject.class, wwwAuthenticate);
DigestWwwAuthenticateSubject wwwAuthenticateSubject = SubjectSerializeUtil.deserialize(wwwAuthenticate, DigestWwwAuthenticateSubject.class);
String username = japUser.getUsername();
String realm = wwwAuthenticateSubject.getRealm();
......@@ -122,7 +122,7 @@ public class HttpApiStrategy extends AbstractJapStrategy {
String ha1 = DigestMD5Util.encode(username, realm, password);
String ha2 = DigestUtil.getHa2ByQop(qop, method, digestUri);
String response = DigestUtil.getResponseByQop(ha1, nonce, nc, cnonce, qop, ha2);
String qopResponse = DigestUtil.getResponseByQop(ha1, nonce, nc, cnonce, qop, ha2);
DigestAuthorizationSubject authorizationSubject = new DigestAuthorizationSubject()
.setCnonce(cnonce)
......@@ -132,14 +132,14 @@ public class HttpApiStrategy extends AbstractJapStrategy {
.setRealm(realm)
.setUsername(username)
.setUri(digestUri)
.setResponse(response)
.setResponse(qopResponse)
.setAlgorithm(wwwAuthenticateSubject.getAlgorithm())
.setOpaque(opaque);
String authStr = SubjectSerializeUtil.serialize(authorizationSubject);
// send authorization request
config.getCustomHeaders().put("Authorization","Digest "+authStr);
config.getCustomHeaders().put("Authorization", "Digest " + authStr);
result = HttpAuthUtil.sendRequest(config.getLoginUrl(),
config.getHttpMethod(),
config.getCustomHeaders(),
......@@ -152,48 +152,46 @@ public class HttpApiStrategy extends AbstractJapStrategy {
return null;
}
private HttpAuthResponse doBasicAuth(JapUser japUser, HttpApiConfig config, HttpServletResponse servletResponse) {
private HttpAuthResponse doBasicAuth(JapUser japUser, HttpApiConfig config, JapHttpResponse response) {
/*
* see: The 'Basic' HTTP Authentication Scheme:https://datatracker.ietf.org/doc/html/rfc7617
*/
String basicAuth = "Basic " + Base64Utils.encode(japUser.getUsername() + ":" + japUser.getPassword());
config.getCustomHeaders().put("authorization",basicAuth);
String basicAuth = "Basic " + Base64.encode(japUser.getUsername() + ":" + japUser.getPassword());
config.getCustomHeaders().put("authorization", basicAuth);
HttpAuthResponse httpAuthResponse = HttpAuthUtil.sendRequest(config.getLoginUrl(),
return HttpAuthUtil.sendRequest(config.getLoginUrl(),
config.getHttpMethod(),
config.getCustomHeaders(),
config.getCustomParams(),
SimpleAuthJsonUtil.getJsonStrByParams(config.getCustomBody()));
return httpAuthResponse;
}
private HttpAuthResponse sendBearerTokenAuthRequest(String token, HttpApiConfig config){
private HttpAuthResponse sendBearerTokenAuthRequest(String token, HttpApiConfig config) {
String bearerToken = "Bearer " + token;
config.getCustomHeaders().put("Authorization",bearerToken);
HttpAuthResponse result = HttpAuthUtil.sendRequest(config.getLoginUrl(),
config.getCustomHeaders().put("Authorization", bearerToken);
return HttpAuthUtil.sendRequest(config.getLoginUrl(),
config.getHttpMethod(),
config.getCustomHeaders(),
config.getCustomParams(),
SimpleAuthJsonUtil.getJsonStrByParams(config.getCustomBody()));
return result;
}
private HttpAuthResponse doBearerAuth(JapUser japUser, HttpApiConfig config, HttpServletResponse servletResponse) {
private HttpAuthResponse doBearerAuth(JapUser japUser, HttpApiConfig config, JapHttpResponse response) {
JapUser japUserInDb = japUserService.getByName(japUser.getUsername());
String token = null;
if (japUserInDb==null||japUserInDb.getToken() == null) {
token = doPreAuthForBearerToken(japUser, config, servletResponse);
}else{
if (japUserInDb == null || japUserInDb.getToken() == null) {
token = doPreAuthForBearerToken(japUser, config, response);
} else {
token = japUserInDb.getToken();
}
HttpAuthResponse result = sendBearerTokenAuthRequest(token, config);
// old token expired, request for new token
if(result==null||!result.isSuccess()){
String newToken = doPreAuthForBearerToken(japUser, config, servletResponse);
if (result == null || !result.isSuccess()) {
String newToken = doPreAuthForBearerToken(japUser, config, response);
result = sendBearerTokenAuthRequest(newToken, config);
}
return result;
......@@ -202,59 +200,59 @@ public class HttpApiStrategy extends AbstractJapStrategy {
/**
* do a pre-auth in Bearer auth to get token for this user
*
* @param japUser
* @param config
* @param servletResponse
* @param japUser jap user
* @param config Http api config
* @param response current http response
*/
private String doPreAuthForBearerToken(JapUser japUser, HttpApiConfig config, HttpServletResponse servletResponse) {
HttpAuthResponse response = null;
private String doPreAuthForBearerToken(JapUser japUser, HttpApiConfig config, JapHttpResponse response) {
HttpAuthResponse httpAuthResponse = null;
// clean old auth token
config.getCustomHeaders().remove("Authorization");
config.getCustomHeaders().remove("authorization");
switch (config.getForBearerTokenEnum()) {
case by_basic:
response = this.doBasicAuth(japUser, new HttpApiConfig(config,config.getBearerTokenIssueUrl()), servletResponse);
case BY_BASIC:
httpAuthResponse = this.doBasicAuth(japUser, new HttpApiConfig(config, config.getBearerTokenIssueUrl()), response);
break;
case by_digest:
response = this.doDigestAuth(japUser, new HttpApiConfig(config,config.getBearerTokenIssueUrl()), servletResponse);
case BY_DIGEST:
httpAuthResponse = this.doDigestAuth(japUser, new HttpApiConfig(config, config.getBearerTokenIssueUrl()), response);
break;
case by_header:
config.getCustomHeaders().put("username",japUser.getUsername());
config.getCustomHeaders().put("password",japUser.getPassword());
response = HttpAuthUtil.sendRequest(config.getLoginUrl(),
config.getHttpMethod(),
config.getCustomHeaders(),
config.getCustomParams(),
SimpleAuthJsonUtil.getJsonStrByParams(config.getCustomBody()));
case BY_HEADER:
config.getCustomHeaders().put("username", japUser.getUsername());
config.getCustomHeaders().put("password", japUser.getPassword());
httpAuthResponse = HttpAuthUtil.sendRequest(config.getLoginUrl(),
config.getHttpMethod(),
config.getCustomHeaders(),
config.getCustomParams(),
SimpleAuthJsonUtil.getJsonStrByParams(config.getCustomBody()));
break;
case by_params:
config.getCustomParams().put("username",japUser.getUsername());
config.getCustomParams().put("password",japUser.getPassword());
response = HttpAuthUtil.sendRequest(config.getLoginUrl(),
config.getHttpMethod(),
config.getCustomHeaders(),
config.getCustomParams(),
SimpleAuthJsonUtil.getJsonStrByParams(config.getCustomBody()));
case BY_PARAMS:
config.getCustomParams().put("username", japUser.getUsername());
config.getCustomParams().put("password", japUser.getPassword());
httpAuthResponse = HttpAuthUtil.sendRequest(config.getLoginUrl(),
config.getHttpMethod(),
config.getCustomHeaders(),
config.getCustomParams(),
SimpleAuthJsonUtil.getJsonStrByParams(config.getCustomBody()));
break;
case by_body:
String body = SimpleAuthJsonUtil.getJsonStrByJapUserAndParams(japUser,config.getCustomBody());
response = HttpAuthUtil.sendRequest(config.getLoginUrl(),
config.getHttpMethod(),
config.getCustomHeaders(),
config.getCustomParams(),
body);
case BY_BODY:
String body = SimpleAuthJsonUtil.getJsonStrByJapUserAndParams(japUser, config.getCustomBody());
httpAuthResponse = HttpAuthUtil.sendRequest(config.getLoginUrl(),
config.getHttpMethod(),
config.getCustomHeaders(),
config.getCustomParams(),
body);
break;
default:
break;
}
// pre-auth field
if (response==null||!response.isSuccess()) {
if (httpAuthResponse == null || !httpAuthResponse.isSuccess()) {
return null;
}
// get token from response body
String token = config.getGetTokenFromResponseStrategy().getToken(response.getBody());
// get token from httpAuthResponse body
String token = config.getGetTokenFromResponseStrategy().getToken(httpAuthResponse.getBody());
if (token == null || token.length() == 0) {
return null;
}
......@@ -268,29 +266,29 @@ public class HttpApiStrategy extends AbstractJapStrategy {
/**
* get user information from request according to http api config.
*
* @param request
* @param config
* @param request current http request
* @param config http api config
* @return jap user contains username and password
*/
public JapUser getJapUser(HttpServletRequest request, HttpApiConfig config) {
public JapUser getJapUser(JapHttpRequest request, HttpApiConfig config) {
JapUser japUser = null;
String username = null;
String password = null;
switch (config.getAuthInfoField()) {
case params:
case PARAMS:
username = request.getParameter("username");
password = request.getParameter("password");
japUser = new JapUser().setUsername(username).setPassword(password);
break;
case header:
case HEADER:
username = request.getHeader("username");
password = request.getHeader("password");
japUser = new JapUser().setUsername(username).setPassword(password);
break;
case body:
case BODY:
try {
// get auth info body from request body.
japUser = config.getRequestBodyToJapUserStrategy().decode(request);
......@@ -312,11 +310,12 @@ public class HttpApiStrategy extends AbstractJapStrategy {
/**
* check http api config.
* NOTICE:
* 1. When use "GET" as request method, custom body is not supported.
* 2. Can not custom body and params at the same time.
* 1. When use "GET" as request method, custom body is not supported.
* 2. Can not custom body and params at the same time.
*
* @param sourceConfig The parameters passed in by the caller
* @param targetConfigClazz The actual parameter class type
* @throws JapException
* @throws JapException Jap exception will be thrown when http api config configuration error
*/
@Override
protected void checkAuthenticateConfig(AuthenticateConfig sourceConfig, Class<?> targetConfigClazz) throws JapException {
......@@ -327,9 +326,9 @@ public class HttpApiStrategy extends AbstractJapStrategy {
config.getHttpMethod() == null ||
config.getLoginUrl() == null ||
config.getAuthInfoField() == null ||
(config.getHttpMethod()==HttpMethodEnum.get&&(config.getCustomBody()!=null&&config.getCustomBody().size()!=0))||
((config.getCustomBody()!=null&&config.getCustomBody().size()!=0)&&(config.getCustomParams()!=null&&config.getCustomParams().size()!=0))
){
(config.getHttpMethod() == HttpMethodEnum.GET && (config.getCustomBody() != null && config.getCustomBody().size() != 0)) ||
((config.getCustomBody() != null && config.getCustomBody().size() != 0) && (config.getCustomParams() != null && config.getCustomParams().size() != 0))
) {
throw new JapException(JapErrorCode.ERROR_HTTP_API_CONFIG);
}
}
......
......@@ -3,10 +3,10 @@ package com.fujieid.jap.httpapi.enums;
/**
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @since 1.0.5
*/
public enum AuthInfoFieldEnum {
header,
params,
body
HEADER,
PARAMS,
BODY
}
......@@ -3,10 +3,10 @@ package com.fujieid.jap.httpapi.enums;
/**
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @since 1.0.5
*/
public enum AuthSchemaEnum {
basic,
digest,
bearer
BASIC,
DIGEST,
BEARER
}
......@@ -3,12 +3,12 @@ package com.fujieid.jap.httpapi.enums;
/**
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @since 1.0.5
*/
public enum ForBearerTokenEnum {
by_header,
by_params,
by_body,
by_basic,
by_digest
BY_HEADER,
BY_PARAMS,
BY_BODY,
BY_BASIC,
BY_DIGEST
}
......@@ -3,9 +3,9 @@ package com.fujieid.jap.httpapi.enums;
/**
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @since 1.0.5
*/
public enum HttpMethodEnum {
post,
get
POST,
GET
}
package com.fujieid.jap.httpapi.strategy;
/**
* Define how to get token from the third-party server's response when request to issue a bearer token
* Define how to get token from the third-party server's response when request to issue a bearer token
*
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @since 1.0.5
*/
@FunctionalInterface
public interface GetTokenFromResponseStrategy {
/**
* get token from body
*
* @param body response body
* @return token
*/
......
package com.fujieid.jap.httpapi.strategy;
import com.fujieid.jap.core.JapUser;
import javax.servlet.http.HttpServletRequest;
import com.fujieid.jap.http.JapHttpRequest;
/**
* Implement this functional interface if your auth info in the request body is not standard json format.
* Implement this functional interface if your auth info in the request body is not standard json format.
*
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @since 1.0.5
*/
@FunctionalInterface
public interface RequestBodyToJapUserStrategy {
/**
* get a JapUser from request
*
* @param request request
* @return JapUser
* @throws Exception
* @throws Exception When the data in the request cannot be decoded, an exception will be thrown
*/
JapUser decode(HttpServletRequest request) throws Exception;
JapUser decode(JapHttpRequest request) throws Exception;
}
......@@ -2,13 +2,14 @@ package com.fujieid.jap.httpapi.subject;
/**
* The Authorization Request Header
* @see <a href="https://en.wikipedia.org/wiki/Digest_access_authentication" target="_blank">https://en.wikipedia.org/wiki/Digest_access_authentication</a>
* @see <a href="https://datatracker.ietf.org/doc/html/rfc2069#section-2.1.2" target="_blank">https://datatracker.ietf.org/doc/html/rfc2069#section-2.1.2</a>
*
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @see <a href="https://en.wikipedia.org/wiki/Digest_access_authentication" target="_blank">https://en.wikipedia.org/wiki/Digest_access_authentication</a>
* @see <a href="https://datatracker.ietf.org/doc/html/rfc2069#section-2.1.2" target="_blank">https://datatracker.ietf.org/doc/html/rfc2069#section-2.1.2</a>
* @since 1.0.5
*/
public class DigestAuthorizationSubject{
public class DigestAuthorizationSubject {
private String username;
private String realm;
private String nonce;
......
......@@ -2,10 +2,11 @@ package com.fujieid.jap.httpapi.subject;
/**
* The WWW-Authenticate Response Header
* @see <a href="https://datatracker.ietf.org/doc/html/rfc2069#section-2.1.1" target="_blank">https://datatracker.ietf.org/doc/html/rfc2069#section-2.1.1</a>
*
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @see <a href="https://datatracker.ietf.org/doc/html/rfc2069#section-2.1.1" target="_blank">https://datatracker.ietf.org/doc/html/rfc2069#section-2.1.1</a>
* @since 1.0.5
*/
public class DigestWwwAuthenticateSubject {
private String realm;
......@@ -16,6 +17,9 @@ public class DigestWwwAuthenticateSubject {
private String stale;
private String qop;
public DigestWwwAuthenticateSubject() {
}
public String getQop() {
return qop;
}
......@@ -25,9 +29,6 @@ public class DigestWwwAuthenticateSubject {
return this;
}
public DigestWwwAuthenticateSubject() {
}
public String getRealm() {
return realm;
}
......
......@@ -5,9 +5,10 @@ import java.util.Map;
/**
* packaging auth result
*
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @since 1.0.5
*/
public class HttpAuthResponse {
private boolean success;
......
package com.fujieid.jap.httpapi.util;
import com.fujieid.jap.core.exception.JapException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* Splice strings by ":", and encode using md5. eg:"MD5(MD5(username:realm:password):nonce:cnonce)"
*
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @since 1.0.5
*/
public final class DigestMD5Util {
private final static String[] HEX_ARRAY = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
public static String encode(String... strs){
public static String encode(String... strs) {
StringBuilder stringBuffer = new StringBuilder();
boolean isFirst = true;
for(String str:strs){
if(isFirst){
for (String str : strs) {
if (isFirst) {
stringBuffer.append(str);
isFirst=false;
}else{
isFirst = false;
} else {
stringBuffer.append(":").append(str);
}
}
// Create an information summary with MD5 algorithm
MessageDigest md = null;
String algorithm = "MD5";
try {
md = MessageDigest.getInstance("MD5");
md = MessageDigest.getInstance(algorithm);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new JapException(algorithm + " not found");
}
byte[] bytes = md.digest(stringBuffer.toString().getBytes());
return byteArrayToHex(bytes);
}
private static String byteArrayToHex(byte[] b){
StringBuffer sb = new StringBuffer();
for (int i = 0; i < b.length; i++) {
sb.append(byteToHex(b[i]));
private static String byteArrayToHex(byte[] b) {
StringBuilder sb = new StringBuilder();
for (byte value : b) {
sb.append(byteToHex(value));
}
return sb.toString();
}
public static String byteToHex(byte b) {
int n = b;
if (n < 0){
if (n < 0) {
n = n + 256;
}
int d1 = n / 16;
int d2 = n % 16;
return HEX_ARRAY[d1]+ HEX_ARRAY[d2];
return HEX_ARRAY[d1] + HEX_ARRAY[d2];
}
}
......@@ -5,9 +5,10 @@ import java.nio.IntBuffer;
/**
* refer: https://github.com/meyfa/java-sha256/blob/master/src/main/java/net/meyfa/sha256/Sha256.java
*
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @since 1.0.5
*/
public class DigestSha256Util {
private static final int[] K = {
......
......@@ -8,33 +8,33 @@ import java.util.concurrent.atomic.LongAdder;
/**
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @since 1.0.5
*/
public final class DigestUtil {
private static final LongAdder LONG_ADDER = new LongAdder();
public static String getCnonce(){
return UUID.randomUUID().toString().replaceAll("-","").substring(0,16);
public static String getCnonce() {
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, 16);
}
public static String getNc(){
public static String getNc() {
LONG_ADDER.increment();
return LONG_ADDER.toString();
}
public static String getResponseByQop(String ha1, String nonce, String nc, String cnonce, String qop, String ha2) {
if(qop!=null&&(qop.contains("auth")||qop.contains("auth-init"))){
return DigestMD5Util.encode(ha1,nonce,nc,cnonce,qop,ha2);
}else{
return DigestMD5Util.encode(ha1,nonce,ha2);
if (qop != null && (qop.contains("auth") || qop.contains("auth-init"))) {
return DigestMD5Util.encode(ha1, nonce, nc, cnonce, qop, ha2);
} else {
return DigestMD5Util.encode(ha1, nonce, ha2);
}
}
public static String getHa2ByQop(String qop, String method, String digestUri) {
if(qop==null||!qop.contains("auth-init")){
return DigestMD5Util.encode(method,digestUri);
}else{
if (qop == null || !qop.contains("auth-init")) {
return DigestMD5Util.encode(method, digestUri);
} else {
// TODO Support "auth-init" ha2 compute method
return null;
}
......
......@@ -3,7 +3,6 @@ package com.fujieid.jap.httpapi.util;
import com.fujieid.jap.httpapi.enums.HttpMethodEnum;
import com.fujieid.jap.httpapi.subject.HttpAuthResponse;
import com.xkcoding.http.HttpUtil;
import com.xkcoding.http.support.SimpleHttpResponse;
import com.xkcoding.http.support.HttpHeader;
import com.xkcoding.http.support.SimpleHttpResponse;
......@@ -13,35 +12,36 @@ import java.util.Map;
/**
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @since 1.0.5
*/
public final class HttpAuthUtil{
public final class HttpAuthUtil {
public static HttpAuthResponse sendRequest(String url,
HttpMethodEnum method,
Map<String,String> header,
Map<String,String> params,
String body){
SimpleHttpResponse response = null;
switch (method){
case get:
response = HttpUtil.get(url, params, new HttpHeader(header), false);
break;
case post:
if(body==null||"".equals(body)){
response = HttpUtil.post(url,params,new HttpHeader(header),false);
}else{
response = HttpUtil.post(url,body,new HttpHeader(header));
}
break;
default:break;
}
if(response==null){
return null;
}
String responseBody = response.getBody();
Map<String, List<String>> headers = response.getHeaders();
return new HttpAuthResponse(response.isSuccess(),responseBody,headers);
public static HttpAuthResponse sendRequest(String url,
HttpMethodEnum method,
Map<String, String> header,
Map<String, String> params,
String body) {
SimpleHttpResponse response = null;
switch (method) {
case GET:
response = HttpUtil.get(url, params, new HttpHeader(header), false);
break;
case POST:
if (body == null || "".equals(body)) {
response = HttpUtil.post(url, params, new HttpHeader(header), false);
} else {
response = HttpUtil.post(url, body, new HttpHeader(header));
}
break;
default:
break;
}
if (response == null) {
return null;
}
String responseBody = response.getBody();
Map<String, List<String>> headers = response.getHeaders();
return new HttpAuthResponse(response.isSuccess(), responseBody, headers);
}
}
package com.fujieid.jap.httpapi.util;
import com.fujieid.jap.core.JapUser;
import java.util.Map;
/**
* Convert between json and auth info
* Convert between json and auth info
*
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @since 1.0.5
*/
public final class SimpleAuthJsonUtil {
public static String getJsonStrByParams(Map<String,String> params){
return getJsonStrByJapUserAndParams(null,params);
public static String getJsonStrByParams(Map<String, String> params) {
return getJsonStrByJapUserAndParams(null, params);
}
public static String getJsonStrByJapUserAndParams(JapUser japUser, Map<String,String> params){
if(japUser==null&&params==null){
public static String getJsonStrByJapUserAndParams(JapUser japUser, Map<String, String> params) {
if (japUser == null && params == null) {
return null;
}
StringBuilder str = new StringBuilder();
str.append("{");
if(japUser!=null){
if (japUser != null) {
str.append("\"username\":\"").append(japUser.getUsername()).append("\",\"password:\"").append(japUser.getPassword()).append("\",");
}
if(params!=null){
if (params != null) {
params.forEach((key, value) -> str.append("\"").append(key).append("\":\"").append(value).append("\","));
}
if(str.charAt(str.length()-1)==','){
str.deleteCharAt(str.length()-1);
if (str.charAt(str.length() - 1) == ',') {
str.deleteCharAt(str.length() - 1);
}
str.append("}");
......
......@@ -7,42 +7,43 @@ import java.util.Objects;
/**
* used to convert "Authorization Request Header" and "WWW-Authenticate Response Header" between string and object
*
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @since 1.0.5
*/
public final class SubjectSerializeUtil {
/**
* Deserialize string to object
* @param clazz
* @param str
* @return
* @throws NoSuchMethodException
* @throws IllegalAccessException
* @throws InvocationTargetException
* @throws InstantiationException
*
* @param str a <code>String</code> to be deserialized
* @param clazz The target type to deserialize
* @return Return an object
* @throws NoSuchMethodException no such method
* @throws IllegalAccessException illegal access
* @throws InvocationTargetException invocation target
* @throws InstantiationException instantiation
*/
public static Object deSerialize(Class<?> clazz,String str) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
str = str.replace("\\","").replace("\"","").trim();
public static <T> T deserialize(String str, Class<T> clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
str = str.replace("\\", "").replace("\"", "").trim();
String[] split = str.split(",");
HashMap<String, String> params = new HashMap<>(8);
for (String s : split) {
String[] param = s.split("=");
String paramKey = param[0].trim();
String paramValue = param[1].trim();
params.put(paramKey,paramValue);
params.put(paramKey, paramValue);
}
Field[] fields = clazz.getDeclaredFields();
Object t = clazz.getDeclaredConstructor().newInstance();
T t = clazz.getDeclaredConstructor().newInstance();
for (Field field : fields) {
field.setAccessible(true);
String name = field.getName();
field.set(t,params.get(name));
field.set(t, params.get(name));
}
return t;
......@@ -50,9 +51,10 @@ public final class SubjectSerializeUtil {
/**
* Serialize object to string
* @param t
* @return
* @throws IllegalAccessException
*
* @param t Objects that need to be serialized
* @return return a <code>string</code> after serialization
* @throws IllegalAccessException illegal access
*/
public static String serialize(Object t) throws IllegalAccessException {
Class<?> clazz = t.getClass();
......@@ -63,10 +65,10 @@ public final class SubjectSerializeUtil {
field.setAccessible(true);
String paramName = field.getName();
String paramVal = ((String) field.get(t));
if(Objects.isNull(paramVal)){
if (Objects.isNull(paramVal)) {
continue;
}
if(!firstParam){
if (!firstParam) {
sb.append(",");
}
firstParam = false;
......
package com.fujieid.jap.httpapi.util;
/**
* URLUtil
* URLUtil
*
* @author zhihai.yu (mvbbb(a)foxmail.com)
* @version 1.0.0
* @since 1.0.0
* @since 1.0.5
*/
public class URLUtil {
......@@ -15,19 +15,20 @@ public class URLUtil {
/**
* Get relative uri from uri.
* https://www.google.com ==>> www.google.com
* @param uri
* @return
*
* @param uri URI with protocol. For example: https://www.google.com
* @return Return only the domain name part in the uri
*/
public static String getRelativeUri(String uri){
if(uri==null){
public static String getRelativeUri(String uri) {
if (uri == null) {
return null;
}
String relativeUri = null;
if(uri.startsWith(HTTPS_PREFIX)){
relativeUri = uri.replaceFirst(HTTPS_PREFIX,"");
}else if(uri.startsWith(HTTP_PREFIX)){
relativeUri = uri.replaceFirst(HTTP_PREFIX,"");
}else{
if (uri.startsWith(HTTPS_PREFIX)) {
relativeUri = uri.replaceFirst(HTTPS_PREFIX, "");
} else if (uri.startsWith(HTTP_PREFIX)) {
relativeUri = uri.replaceFirst(HTTP_PREFIX, "");
} else {
relativeUri = uri;
}
relativeUri = relativeUri.substring(relativeUri.indexOf('/'));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册