All Downloads are FREE. Search and download functionalities are using the official Maven repository.

club.zhcs.rop.checker.ROPServerRSASignatureVerifier Maven / Gradle / Ivy

package club.zhcs.rop.checker;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;

import org.nutz.http.Http;
import org.nutz.lang.Lang;
import org.nutz.lang.Streams;
import org.nutz.lang.Strings;
import org.nutz.log.Logs;

import club.zhcs.rop.core.ROPConsts;
import club.zhcs.rop.core.signer.KeyPairFetcher;
import club.zhcs.rop.core.signer.SignerHelper;

/**
 * 
 * @author Kerbores([email protected])
 *
 */
public class ROPServerRSASignatureVerifier implements ServerSignatureVerifier {

    ServerKeyPairFetcher fetcher;

    public ROPServerRSASignatureVerifier(ServerKeyPairFetcher fetcher) {
        super();
        this.fetcher = fetcher;
    }

    @Override
    public boolean verification(HttpServletRequest request) {
        if (Strings.isBlank(request.getHeader(ROPConsts.PUBLIC_KEY_KEY))
            || Strings.isBlank(request.getHeader(ROPConsts.TS_KEY))
            || Strings.isBlank(request.getHeader(ROPConsts.METHOD_KEY))
            || Strings.isBlank(request.getHeader(ROPConsts.NONCE_KEY))
            || Strings.isBlank(request.getHeader(ROPConsts.SIGN_KEY))) {
            return false;
        }
        String sign = request.getHeader(ROPConsts.SIGN_KEY);
        Logs.get().debugf("Expected sign is %s", sign);

        return verification(request.getHeader(ROPConsts.PUBLIC_KEY_KEY),
                            request.getHeader(ROPConsts.TS_KEY),
                            request.getHeader(ROPConsts.METHOD_KEY),
                            request.getHeader(ROPConsts.NONCE_KEY),
                            getDataMate(request),
                            sign);
    }

    public String contentType(HttpServletRequest request) {
        return request.getHeader("Content-Type");
    }

    protected String getDataMate(HttpServletRequest request) {
        if (Strings.equalsIgnoreCase(request.getMethod(), "GET")) {// GET请求需要处理一下
            return Lang.md5(Http.encode(request.getQueryString(), request.getCharacterEncoding()));
        }
        // 文件上传
        if (isFileUpload(request)) {
            try {
                return Lang.md5(new ByteArrayInputStream(
                                                         getUrlEncodedParams(request).getBytes(request.getCharacterEncoding())));
            }
            catch (IOException | ServletException e) {
                Logs.get().debug("不支持的编码!");
                throw Lang.wrapThrow(e);
            }
        }
        try {
            StringBuilder info = Streams.read(new InputStreamReader(request.getInputStream()));
            if (info.length() == 0) {
                return Lang.md5(
                                SignerHelper.paramMapAsUrlString(request.getParameterMap(), request.getCharacterEncoding()));
            }
            return Lang.md5(info);
        }
        catch (IOException e) {
            throw Lang.wrapThrow(e);
        }
    }

    public String getUrlEncodedParams(final HttpServletRequest request) throws IOException, ServletException {
        final StringBuilder sb = new StringBuilder();
        List parts = Lang.collection2list(request.getParts());
        Collections.sort(parts, (part1, part2) -> part1.getName().compareTo(part2.getName()));
        parts.stream().forEach(part -> {
            String key = part.getName();
            if (Strings.isBlank(part.getContentType())) {
                // 参数
                sb.append(Http.encode(key, request.getCharacterEncoding()))
                  .append('=')
                  .append(Http.encode(request.getParameter(key), request.getCharacterEncoding()))
                  .append('&');
            } else {
                // 文件
                try {
                    sb.append(Http.encode(key, request.getCharacterEncoding()))
                      .append('=')
                      .append(Http.encode(Lang.md5(part.getInputStream()), request.getCharacterEncoding()))
                      .append('&');
                }
                catch (IOException e) {
                    throw Lang.wrapThrow(e);
                }
            }
        });

        if (sb.length() > 0) {
            sb.setLength(sb.length() - 1);
        }
        return sb.toString();

    }

    private boolean isCommonFileUpload(HttpServletRequest request) {
        return contentType(request) != null && contentType(request).startsWith("multipart/form-data");
    }

    /**
     * @param request
     * @return
     */
    private boolean isFileUpload(HttpServletRequest request) {
        return isCommonFileUpload(request) || isHtml5FileUpload(request);
    }

    private boolean isHtml5FileUpload(HttpServletRequest request) {
        return contentType(request) != null && contentType(request).startsWith("application/octet-stream");
    }

    @Override
    public KeyPairFetcher fetcher() {
        return fetcher;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy