10-environment

1. ip

1. 服务端ip

public static String getHostIP() {
    String sIP = "";
    InetAddress ip = null;
    try {
        // Windows操作系统
        if (isWindowsOS()) {
            ip = getLocalHost();
        }
        // Linux操作系统
        else {
            boolean bFindIP = false;
            Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces();
            while (netInterfaces.hasMoreElements()) {
                if (bFindIP) {
                    break;
                }
                NetworkInterface ni = netInterfaces.nextElement();
                // 遍历所有ip
                Enumeration<InetAddress> ips = ni.getInetAddresses();
                while (ips.hasMoreElements()) {
                    ip = ips.nextElement();
                    // 开头的都是lookback地址
                    if (ip.isSiteLocalAddress() && !ip.isLoopbackAddress() && !getInetAddress(ip).contains(":")) {
                        // 进行ip模式匹配
                        if (getInetAddress(ip) != null) {
                            bFindIP = true;
                            break;
                        }
                    }
                }
            }
        }
    } catch (Exception e) {
        if (logger.isErrorEnabled()) {
            logger.error("获取本机ip地址失败", e);
        }
    }
    if (null != ip) {
        sIP = getInetAddress(ip);
    }
    return sIP;
}

private static boolean isWindowsOS() {
    boolean isWindowsOS = false;
    String osName = System.getProperty("os.name");
    if (osName != null && osName.toLowerCase().contains("windows")) {
        isWindowsOS = true;
    }
    return isWindowsOS;
}

private static InetAddress getLocalHost() {
    try {
        return InetAddress.getLocalHost();
    } catch (UnknownHostException e) {
        throw new RuntimeException(e);
    }
}

private static String getInetAddress(InetAddress ip) {
    return ip.getHostAddress();
}






 

















 













 






 








 






 

2. 请求端ip


在通过了Apache, Squid等反向代理软件就不能获取到客户端的真实IP地址了,如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串IP值, 究竟哪个才是真正的用户端的真实IP呢?

  • X-Forwarded-For中第一个非unknown的有效IP字符串
  • eg:X-Forwarded-For: 192.168.1.110, 192.168.1.120, 192.168.1.130, 192.168.1.100。用户真实IP为:192.168.1.110
private String getRemoteIpAddr(HttpServletRequest request) {
    // nginx代理获取的真实用户ip
    String ip = request.getHeader("X-Real-IP");
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("x-forwarded-for");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("WL-Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("HTTP_CLIENT_IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getHeader("HTTP_X_FORWARDED_FOR");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        ip = request.getRemoteAddr();
        if (ip.equals("127.0.0.1")) {
            // 根据网卡取本机配置的IP
            InetAddress inet = null;
            try {
                inet = InetAddress.getLocalHost();
            } catch (Exception e) {
                e.printStackTrace();
            }
            assert inet != null;
            ip = inet.getHostAddress();
        }
    }
    // 多个代理的情况,第一个IP为客户端真实IP,多个IP按照`,`分割
    if (ip != null && ip.length() > 15) {
        if (ip.indexOf(",") > 0) {
            ip = ip.substring(0, ip.indexOf(","));
        }
    }
    return ip;
}

1. SameSize

内嵌iframe页面获取不到外层页面cookieticket

anN3ZDBST2xoQ204Mk44ZU10QjlJdE9ENVJpR2xiTUU1cTNkcHI4PQ==

https:

bVo0RkFVT3NVTGU1QXVEcGQxUEQyOU9ENVJpR2xiTUU1cTNkcHIvUk53PT0=

谷歌浏览器90以后只能后端来控制了samesize,https后端来设置。http仍然可以前端来设置

String cookieTicketKey = "";
String token = "";
if (StrUtil.isNotBlank(cookieTicketKey)) {
    ResponseCookie cookie = ResponseCookie.from(cookieTicketKey, token)
                                .path("/")
                                .secure(true)
                                .sameSite("None")
                                .build();
    response.setHeader(HttpHeaders.SET_COOKIE, cookie.toString());
}

3. Https

OKhttp忽略https证书open in new window

1. 忽略https证书

String resEncrypt = HttpRequest.post(url)
        .setSSLSocketFactory(SslSocketClient.getSslSocketFactory())
        .setHostnameVerifier(SslSocketClient.getHostnameVerifier())
        .body(gson.toJson(reqMap))
        .timeout(8000)
        .execute().body();
import javax.net.ssl.*;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

/**
 * @author: lisongtao
 * @description: SslSocketClient
 * @create: 2021-03-16 21:31
 */
public class SslSocketClient {

    /**
     * SSLSocketFactory
     * 通过这个类我们可以获得SSLSocketFactory,这个东西就是用来管理证书和信任证书的
     *
     * @return SSLSocketFactory
     */
    public static SSLSocketFactory getSslSocketFactory() {
        try {
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, getTrustManager(), new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取TrustManager
     *
     * @return TrustManager[]
     */
    private static TrustManager[] getTrustManager() {
        // 不校检证书链
        return new TrustManager[]{
                new X509TrustManager() {

                    /**
                     * 不校检客户端证书
                     * @param chain chain
                     * @param authType authType
                     */
                    @Override
                    public void checkClientTrusted(X509Certificate[] chain, String authType) {
                    }

                    /**
                     * 不校检服务器证书
                     * @param chain chain
                     * @param authType authType
                     */
                    @Override
                    public void checkServerTrusted(X509Certificate[] chain, String authType) {
                    }

                    /**
                     * OKhttp3.0以前返回null,3.0以后返回new X509Certificate[]{};
                     * @return X509Certificate[]
                     */
                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[]{};
                    }
                }
        };
    }

    /**
     * 获取HostnameVerifier
     *
     * @return HostnameVerifier
     */
    public static HostnameVerifier getHostnameVerifier() {
        return new HostnameVerifier() {
            /**
             * 未真正校检服务器端证书域名
             * @param s s
             * @param sslSession sslSession
             * @return boolean
             */
            @Override
            public boolean verify(String s, SSLSession sslSession) {
                return true;
            }
        };
    }

}

4. bean覆盖

  • 允许bean覆盖之前相同名称的bean
  • allow-bean-definition-overriding
spring:
  application:
    name: ooxx
  profiles:
    active: prod
  main:
    allow-bean-definition-overriding: true