后台服务器搭建和运维时遇到的一些问题

问题记录与学习思考

2016-04-20 | 阅读

配置跨域共享

跨域资源共享 CORS,是一种网络浏览器的技术规范,允许网页从不同的域访问资源,而这种访问是被同源策略所禁止的.CORS是为了让AJAX可以实现可控的跨域访问.

如果使用了Nginx进行端口转发,需要配置:

if ($request_method = 'OPTIONS') {  
          add_header 'Access-Control-Allow-Origin' '*';  
          add_header 'Access-Control-Allow-Credentials' 'true';  
          add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';  
          add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';  
         # add_header 'Access-Control-Max-Age' 1728000;  
          add_header 'Content-Type' 'text/plain charset=UTF-8';  
          add_header 'Content-Length' 0;  
          return 200;  
        }  

然后使用Tomcat自带的CORS过滤器,在web.xml上配置:

<filter>
		<description>跨域</description>
		<filter-name>CorsFilter</filter-name>
		<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
		<init-param>
			<param-name>cors.allowed.origins</param-name>
			<param-value>*</param-value>
		</init-param>
		<init-param>
			<param-name>cors.allowed.methods</param-name>
			<param-value>GET,POST,OPTIONS</param-value>
		</init-param>
		<init-param>
			<param-name>cors.allowed.headers</param-name>
			<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,EnvParams,channel,publicChannel</param-value>
		</init-param>
		<init-param>
			<param-name>cors.exposed.headers</param-name>
			<param-value>Access-Control-Allow-Origin,Access-Control-Allow-Credentials</param-value>
		</init-param>
		<init-param>
			<param-name>cors.support.credentials</param-name>
			<param-value>true</param-value>
		</init-param>
		<init-param>
			<param-name>cors.preflight.maxage</param-name>
			<param-value>86400</param-value>
		</init-param>
	</filter>

单机多tomcat配置

首先端口不能冲突,一个是启动端口,一个是关闭端口.

然后,在tomcat启动时,会在执行catalina.sh获取CATALINA_HOME这个变量,而如果之前有一个tomcat正在运行,会设置上这个变量,导致新的tomcat加载了旧的变量,而直接把旧的tomcat给关闭了.所以,要在启动第二个tomcat时,使其正确启动,就要直接在catalina.sh上设置上属性:

export CATALINA_BASE=$CATALINA_2_BASE
export CATALINA_HOME=$CATALINA_2_HOME   这里需要设置两个全局变量,在`/etc/profile`中声明这两个全局变量:

CATALINA_2_BASE=/usr/local/tomcat_2
CATALINA_2_HOME=/usr/local/tomcat_2
export CATALINA_2_BASE CATALINA_2_HOME   当然,这样做之后,启动tomcat时,就需要按顺序来启动,先启动第一个,然后才启动第二个tomcat.或者直接在第一个tomcat上也设置上`CATALINA_1_HOME`的参数,就不会有个先后的限定了.

Nginx配置转发https

在转发项中,添加一个设置:

proxy_set_header X-Forwarded-Proto  $scheme;

然后再添加一个转发重定向:

proxy_redirect http:// https://;

然后在tomcat的server.xml中的Engine下配置一个Value:

<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="X-Forwarded-For" protocolHeader="X-Forwarded-Proto" protocolHeaderHttpsValue="https"/>

Tomcat配置https

使用keytool生成证书:

// 输入的姓名要为当前证书对应的域名
keytool -genkey -alias app -keyalg RSA -keystore appkey
keytool -export -file app.crt -alias app -keystore appkey

为JVM导入证书:

keytool -import -keystore $JAVA_HOME/jre/lib/security/appcacerts -file app.crt -alias app

出现错误:

keytool 错误: java.io.IOException: Keystore was tampered with, or password was incorrect

因为$JAVA_HOME/jre/lib/security/appcacerts最后一个表示生成的密钥库的名称,当前目录下已经有这个密钥库的话,就会失败,重新命名或者,删除之前的.

然后配置tomcat :

<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
           maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
           clientAuth="false" sslProtocol="TLS"
           //key的路径
            keystoreFile="/root/sshKeys/app/appkey" 
            // 密码
            keystorePass="123456" />

重启tomcat,测试一下.失败,服务器上可以访问,但是其他地方访问不了.

Nginx反向代理Tomcat时,nginx端配置https,转发http给tomcat

配置https,只要nginx端配置上https就可以了,没必要nginx和tomcat一起配置https. nginx转发到tomcat的安全性可以通过防火墙限制ip来处理.

nginx的配置,

server {
        listen 443 ssl;
        server_name  app.luoxianming.cn;

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
        ssl_certificate  /usr/local/nginx/conf/httpsCA/blog.luoxianming.cn.crt;
        ssl_certificate_key  /usr/local/nginx/conf/httpsCA/blog.luoxianming.cn.key;
        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;
        location / {
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                #但是设置转发的header上是https头.
                proxy_set_header X-Forwarded-Proto https;
                proxy_redirect off;
                proxy_connect_timeout      240;
                proxy_send_timeout         240;
                proxy_read_timeout         240;
                client_max_body_size 20M;
        			#直接转发http协议,而不是https协议
                proxy_pass http://127.0.0.1:8080/memoplus/;
        }
    }

tomcat的配置:

// 设置代理端口和转发端口为443,即nginx的ssl端口
<Connector port="8080" protocol="HTTP/1.1"
           connectionTimeout="20000"
            redirectPort="443"
           proxyPort="443" />

// 顺便在Engine中配置获取反向代理后的一些头信息.      
<Valve className="org.apache.catalina.valves.RemoteIpValve"
              remoteIpHeader="x-forwarded-for"
              remoteIpProxiesHeader="x-forwarded-by"
              protocolHeader="x-forwarded-proto"
        />

Cookie与Session

两者都是用来解决http是无状态的连接的问题,但是session是保存在服务器端的少量数据,而cookie是保存在客户端的大量数据.

由于采取在服务器端保持状态,即session,但也需要在客户端放置一个标识,所以session机制需要借助cookie来实现在客户端的保存. 在服务器端设置session时,实际传递了一个Set Cookie给客户端,而客户端每次访问后台时,都会带上这个Cookie给服务器端,服务器根据Cookie中的SessionID来判断客户所在的Session.

当前我用的域名是app.luoxianming.cn,通过nginx反向代理到一个tomcat下的memoplus项目,结果自动生成的Cookie的Domainapp.luoxianming.cn,而path设置为了memoplus,但是我客户端直接访问的就是app.luoxianming.cn,我这个tomcat下面就只有这一个项目,但是被设置了path,导致请求没有正确带上Cookie.

要处理这个问题,那就在初始化session的时候,也同时设置好正确的Cookie返回.

在tomcat的context.xml文件中配置cookie的Path和SessionName:

<Context sessionCookiePath="/" sessionCookieName="LXMSESSION">