網頁

顯示具有 網頁設計 標籤的文章。 顯示所有文章
顯示具有 網頁設計 標籤的文章。 顯示所有文章

2025年2月19日 星期三

安裝 ollama open-webui nginx

參考 https://github.com/ollama/ollama
參考 https://hub.docker.com/r/ollama/ollama
參考 https://www.53ai.com/news/OpenSourceLLM/2024072585037.html

$ docker run -d --gpus=all -p 11434:11434 --name ollama \
  -v /mnt/Data/ollama/ollama_volume:/root/.ollama \
  ollama/ollama
$ docker exec -it ollama ollama run deepseek-r1
$ git clone https://github.com/ggerganov/llama.cpp.git
$ cd llama.cpp
$ cmake -B build
$ cmake --build build --config Release
$ pip install huggingface_hub

轉換 huggingface 上的 model, 成為 GGUF 格式
vi download.py 
from huggingface_hub import snapshot_download, login

login("hf_BqLATKBqbVzOWNBJcFMwHKzCJfu")

# 下载模型
snapshot_download(
    "taide/Llama-3.1-TAIDE-LX-8B-Chat",
    local_dir="taide_Llama-3.1-TAIDE-LX-8B-Chat",
    local_dir_use_symlinks=False,
    ignore_patterns=["*.gguf"]
)

$ vi convert_hf_to_gguf_update.py
在 models 中, 加入下行, 注意 TOKENIZER_TYPE 的選擇
    {"name": "taide_Llama-3.1-TAIDE-LX-8B-Chat", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/taide/Llama-3.1-TAIDE-LX-8B-Chat"},
    {"name": "yentinglin_Llama-3-Taiwan-8B-Instruct", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/yentinglin/Llama-3-Taiwan-8B-Instruct"},
$ python convert_hf_to_gguf_update.py hf_BqLATKBqbVzOWNBJcFMwHKzCJfu
$ python convert_hf_to_gguf.py taide_Llama-3.1-TAIDE-LX-8B-Chat --outtype f16 --outfile taide_Llama-3.1-TAIDE-LX-8B-Chat.fp16.gguf
$ llama.cpp/build/bin/llama-quantize taide_Llama-3.1-TAIDE-LX-8B-Chat.fp16.gguf Q4_K_M
$ mv ggml-model-Q4_K_M.gguf taide_Llama-3.1-TAIDE-LX-8B-Chat-Q4_K_M.gguf
$ vi Modelfile.taide-8b
FROM ./yentinglin_Llama-3-Taiwan-8B-Instruct.Q4_K_M.gguf
# set the temperature to 1 [higher is more creative, lower is more coherent]
PARAMETER temperature 1
# set the system message
SYSTEM """
我是一個萬事通
"""

$ docker exec -it ollama /bin/bash
# cd /root/.ollama
# ollama create taide-8b -f ./Modelfile.taide-8b
# ollama list
# ollama show taide-8b
# ollama rm taide-8b
# ollama ps
# ollama run taide-8b
>>> /bye
# OLLAMA_HOST=127.0.0.1:11434 ollama serve
$ curl http://localhost:11434/api/generate -d '{
  "model": "yentinglin-8b", 
  "prompt": "建議適合ai的程式語言"
}'
$ curl http://localhost:11434/api/generate -d '{
  "model": "yentinglin-8b", 
  "prompt": "建議適合ai的程式語言",
  "stream", false
}'
$ curl http://localhost:11434/api/chat -d '{
  "model": "yentinglin-8b", 
  "messages": [
    {"role": "user", "content": "建議適合ai的程式語言"}
  ]
}'
$ curl http://localhost:11434/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{
        "model": "yentinglin-8b",
        "messages": [
            {
                "role": "system",
                "content": "你是一個萬事通"
            },
            {
                "role": "user",
                "content": "眼睛酸痛,怎麼辦?"
            }
        ]
    }'

$ docker logs ollama

$ python ../llama.cpp/convert_hf_to_gguf.py yentinglin_Llama-3-Taiwan-8B-Instruct --outtype f16 --outfile yentinglin_Llama-3-Taiwan-8B-Instruct.fp16.gguf
$ llama.cpp/build/bin/llama-quantize yentinglin_Llama-3-Taiwan-8B-Instruct.fp16.gguf Q4_K_M


建議適合ai的程式語言

$ docker run -d -p 3000:8080 --gpus all \
  --add-host=host.docker.internal:host-gateway \
  -v /mnt/Data/ollama/open-webui_volume:/app/backend/data \
  --name open-webui \
  --restart always \
  ghcr.io/open-webui/open-webui:cuda
  
Firefox Web Browser 輸入 http://localhost:3000
出現 This address is restricted 錯誤
進入 Firefox Web Browser 設定
網址列輸入 about:config, 按 "Accept the Risk and Continue" 按鈕
在收尋欄輸入 network.security.ports.banned.override, 點選 "String", 按 +
輸入 port 3000, 按 V
重新載入 http://localhost:3000

chrome 設定
chrome://flags/#unsafely-treat-insecure-origin-as-secure
輸入網址 http://localhost:3000

安裝 nginx
參考 https://docs.openwebui.com/tutorials/https-nginx/
參考 https://yingrenn.blogspot.com/2020/07/ssl-nginx.html
vi nginx.conf
server {
    listen 443 ssl;
    server_name  www.domain.com.tw;
    ssl_certificate /etc/nginx/conf/Certs/server.pem;
    ssl_certificate_key /etc/nginx/conf/Certs/server.key;
    ssl_trusted_certificate /etc/nginx/conf/Certs/caChain.crt;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers on;
    
    location / {
        proxy_set_header HOST $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://host.docker.internal:3000;
        
        # Add WebSocket support (Necessary for version 0.5.0 and up)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # (Optional) Disable proxy buffering for better streaming response from models
        proxy_buffering off;
    }
}
server {
     listen 80;
     server_name www.domain.com.tw;
     return 301 https://$host$request_uri; 
}

docker run -itd --name nginx \
  -p 80:80 -p 443:443 \
  --add-host=host.docker.internal:host-gateway \
  -v /mnt/Data/ollama/nginx/conf.d/nginx.conf:/etc/nginx/conf.d/nginx.conf \
  -v /mnt/Data/ollama/nginx/conf:/etc/nginx/conf \
  -m 100m library/nginx:latest

https://www.domain.com.tw

2020年7月20日 星期一

SSL 證書安裝於 Nginx

參考 SSL 憑證服務 操作手冊
參考 檢查 HTTPS 伺服器加密協定版本
參考 https on nginx and python flask
參考 https Client and Server

取得三個證書
1. eCA 根憑證 "ROOTeCA_64.crt"
2. PublicCA G2 中繼憑證 "PublicCA2_64.crt"
3. 用戶的 SSL 伺服器憑證 "xxx...(32個英數字).crt"

# mkdir /etc/nginx/conf/Certs
放三個證書於此目錄
# cp * /etc/nginx/conf/Certs
產生可信任的CA憑證串列
# cd /etc/nginx/conf/Certs
# cat PublicCA_64.crt ROOTeCA_64.crt > caChain.crt
因 Nginx 只能使用未加密的 server key
# openssl rsa -in server.key -out server_no_pwd.key
# cat server_no_pwd.key > /etc/nginx/conf/Certs/server.key
# cat xxx...(32個英數字).crt PublicCA2_64.crt > server.pem


修改 /etc/nginx/sites-available/ 下的設定檔
        ssl_certificate /etc/nginx/conf/Certs/server.pem;
        ssl_certificate_key /etc/nginx/conf/Certs/server.key;
        ssl_stapling on;
        ssl_stapling_verify on;

        ssl_trusted_certificate /etc/nginx/conf/Certs/caChain.crt;

修改 /etc/nginx/nginx.conf        # 關閉有漏洞的 HTTPS SSLv3, 採用 TLS
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

# ngnix -s reload

測試安全性
$ sudo apt install nmap
$ nmap --script ssl-enum-ciphers -p 8443 www.xxxx.com

Starting Nmap 7.60 ( https://nmap.org ) at 2020-07-20 14:21 CST
Nmap scan report for www.xxxx.com.tw (114.35.104.33)
Host is up (0.00057s latency).
rDNS record for 114.35.14.313: 114-35-104-33.HINET-IP.hinet.net

PORT     STATE SERVICE
8443/tcp open  https-alt
| ssl-enum-ciphers:
|   TLSv1.0:
|     ciphers:
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
|     compressors:
|       NULL
|     cipher preference: server
|   TLSv1.1:
|     ciphers:
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
|     compressors:
|       NULL
|     cipher preference: server
|   TLSv1.2:
|     ciphers:
|       TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CCM_8 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CCM (rsa 2048) - A
|       TLS_RSA_WITH_ARIA_256_GCM_SHA384 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CCM_8 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CCM (rsa 2048) - A
|       TLS_RSA_WITH_ARIA_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
|     compressors:
|       NULL
|     cipher preference: server
|_  least strength: A

Nmap done: 1 IP address (1 host up) scanned in 0.41 seconds

測試結果分為等級 A-F


下載 認證標章,並放置下列HTML語法到網頁
<a href="javascript:location.href='https://publicca.hinet.net/SSLQueryCert/ SSLQueryCert.jsp?Domain_name='+document.location.hostname">
<img height="126" src="SSLSeal.gif" width="90" />
</a>

2020年3月23日 星期一

ubuntu eclipse install

參考 Ubuntu 1804 桌面版 Eclipse + JSP 學習記錄
$ java -version
openjdk version "11.0.6" 2020-01-14
OpenJDK Runtime Environment (build 11.0.6+10-post-Ubuntu-1ubuntu118.04.1)
OpenJDK 64-Bit Server VM (build 11.0.6+10-post-Ubuntu-1ubuntu118.04.1, mixed mode, sharing)
$ sudo update-alternatives --config java
There are 2 choices for the alternative java (providing /usr/bin/java).

  Selection    Path                                            Priority   Status
------------------------------------------------------------
* 0            /usr/lib/jvm/java-11-openjdk-amd64/bin/java      1111      auto mode
  1            /usr/lib/jvm/java-11-openjdk-amd64/bin/java      1111      manual mode
  2            /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java   1081      manual mode

Press <enter> to keep the current choice[*], or type selection number:
$ vi ~/.bashrc
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
export CLASSPATH=.:${JAVA_HOME}/lib
export PATH=${JAVA_HOME}/bin:${PATH}
$ source ~/.bashrc
到網頁 https://www.eclipse.org/
找到要下載的 linux 64 bit 版本 https://www.eclipse.org/downloads/download.php?file=/oomph/epp/2020-03/R/eclipse-inst-linux64.tar.gz
$ cd Downloads/
$ tar xvf eclipse-inst-linux64.tar.gz
$ cd eclipse-installer/
為避免
Caused by: java.io.FileNotFoundException: /home/user1/Downloads/eclipse-installer/configuration/org.eclipse.osgi/.manager/.fileTableLock (Permission denied)
$ sudo chown -RH mark: configuration/
有人使用 $ sudo ./eclipse-inst, 但安裝完成後,只能用 $ sudo ./eclipse 啟動
$ ./eclipse 會出現 /root/.p2/pool/plugins/org.eclipse.equinox.launcher.gtk.linuxx86_64.1.1.1100.v20190907-0426: cannot open shared object file: Permission denied
$ ./eclipse-inst
選擇 Eclipse IDE for Enterprise Java Developers
選擇 java 版本和安裝路徑
$ sudo rm -rf eclipse-installer/ eclipse-inst-linux64.tar.gz
$ cd

安裝桌面啟動捷徑
$ vi ~/.local/share/applications/eclipse.desktop
[Desktop Entry]
Type=Application
Name=Eclipse
Comment=Eclipse Integrated Development Environment
Icon=/home/user1/eclipse/jee-2020-03/eclipse/icon.xpm
Exec=/home/user1/eclipse/jee-2020-03/eclipse/eclipse
Terminal=false
Categories=Development
StartupWMClass=Eclipse

$ chmod +x ~/.local/share/applications/eclipse.desktop
重新開機
按 Search, 找 Eclipse, 按右鍵, Add to Favorites

Eclipse 設定 Tomcat server
$ wget http://ftp.tc.edu.tw/pub/Apache/tomcat/tomcat-9/v9.0.33/bin/apache-tomcat-9.0.33.tar.gz
$ tar xvf apache-tomcat-9.0.33.tar.gz
開啟 eclipse
Window/Preferences
Server/Runtime Environment
按 Add, 選擇 Apache Tomcat v9.0
設定 Tomcat installation directory: 到剛才解壓縮的路徑
Window/Show View/Other...
選擇 Servers
按 ProjectExplorer/Servers/Tomcat v9.0 Server at localhost-config/server.xml
修改 port

建立 Eclipse 專案
File/New/Dynamic Web Project
輸入專案名稱
在 Web Module 頁中,將 Generate web.xml deployment descriptor 打勾
Project Explorer/專案名稱/WebContent 右鍵 New/JSP File

下載 gson-2.8.6.jar 到 專案下的 WEB-INF/lib 下


處理 json

Project Explorer/專案名稱 右鍵 Export/WAR file

2020年3月18日 星期三

https on nginx and python flask

建立 python flask 的網頁伺服器
$ cat server.py
@app.route('/api/PostTime', methods=['POST'])
def post_time():
    print(request.headers)
    print(request.json)
    result = '\n'.join([request.json['updDate'],
            request.json['camera']])
    print(result)
    return str(result)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port="5000", debug=True,
            # 下兩行可以啟動 https
            #ssl_context=("/home/user1/Data/webapi/openssl/web1/server.crt",
            #    "/home/user1/Data/webapi/openssl/web1/server.key")
            )

$ python3 server.py

$ cat PostTime.py
import requests
import os

data = {
    'updDate': '2019-01-02T15:10:11',
    'camera': 'A001',
}

os.environ['REQUESTS_CA_BUNDLE'] = '/home/user1/Data/webapi/openssl/ca/cacert.pem'
#url = 'https://127.0.0.1:5000/api/PostTime'
url = 'https://127.0.0.1:8443/api/PostTime'
headers = {'Content-Type': 'application/json'}
response = requests.post(url=url,
        headers=headers,
        #verify=False,
        json=data)
if response.ok:
    print("PostTime ok")
    print(response.status_code)
    print(response.text)
else:
    print(response.status_code)
    print(response.text)

$ python3 PostTime.py

# cat /etc/nginx/sites-available/config
server {
        listen 80 default_server;
        listen [::]:80 default_server;

        # SSL configuration
        #
        listen 8443 ssl default_server;
        listen [::]:8443 ssl default_server;
        ssl_certificate /home/user1/Data/webapi/openssl/web1/server.crt;
        ssl_certificate_key /home/user1/Data/webapi/openssl/web1/server.key;
        root /var/www/html;

        # Add index.php to the list if you are using PHP
        index index.html index.htm index.nginx-debian.html;

        server_name _;

        location ^~ /api/ {
                # 當 https 由 nginx 管控,python flask 就要走一般的 http
                proxy_pass http://127.0.0.1:5000;
                proxy_set_header Host $host;
        }
        # 設定上傳限制
        client_max_body_size 10M;
}

重新啟動 nginx
# sudo nginx -s reload

2017年4月17日 星期一

OpenSSL 證書

openssl学习笔记--CA及https网站证书配置

root@arduino:~/openssl# mkdir openssl
root@arduino:~/openssl# cd openssl
root@arduino:~/openssl# mkdir private
// 產生 根私鑰
root@arduino:~/openssl# openssl genrsa -out private/cakey.pem 2048
root@arduino:~/openssl# vi /etc/ssl/openssl.cnf
dir             = /root/openssl         # Where everything is kept
default_md = sha512 # 使用預設(sha1)方法,chrome 會報說此方法已經不安全,不給用
ountryName                     = Country Name (2 letter code)
countryName_default             = TW
stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = Taiwan
localityName                    = Locality Name (eg, city)
localityName_default            = Taichung
0.organizationName              = Organization Name (eg, company)
0.organizationName_default      = SDL
organizationalUnitName          = Organizational Unit Name (eg, section)
organizationalUnitName_default  = R&D

// 產生 根證書
root@arduino:~/openssl# openssl req -new -x509 -key private/cakey.pem -out cacert.pem -days 3650
root@arduino:~/openssl# touch index.txt serial
root@arduino:~/openssl# echo 01 >serial
root@arduino:~/openssl# mkdir newcerts
root@arduino:~/openssl# mkdir web1
// 產生網站要用的私鑰,通常在別台電腦
root@arduino:~/openssl# openssl genrsa -out web1/httpd.key 2048
root@arduinoYun:~/openssl# cp /etc/ssl/openssl.cnf web1/
root@arduinoYun:~/openssl# vi web/openssl.cnf
req_extensions = v3_req # The extensions to add to a certificate request
[ v3_req ]
subjectAltName = @alt_names
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
[alt_names]
IP.1 = 192.168.1.61
IP.2 = 192.168.240.1
IP.3 = 192.168.43.201
DNS.1 = arduinoyun.local

// 產生證書申請書
root@arduino:~/openssl# openssl req -new -key web1/httpd.key -out web1/httpd.csr -sha512 -config web1/openssl.cnf
// 填入要簽署的網址
Common Name (e.g. server FQDN or YOUR name) []:Arduino Yun
// 下面兩個不要填
A challenge password []:
An optional company name []:

// 可用下面命令,查看證書申請
root@arduinoYun:~/openssl# openssl req -text -noout -in web1/httpd.csr
// 將證書申請書送到根證書的機器,簽屬證書
root@arduino:~/openssl# openssl ca -in web1/httpd.csr -out web1/httpd.crt -days 3650 -extensions v3_req -extfile web1/openssl.cnf
// 回答兩個 y 即可,若發生下列錯誤,查詢 newcerts 目錄下最後的一個 pem
failed to update database
TXT_DB error number 2
// 使用命令
root@arduinoYun:~/openssl# openssl ca -revoke newcerts/02.pem

root@arduino:~/openssl# cd ..
root@arduino:~# vi pythonWeb.py
  server.socket = ssl.wrap_socket(server.socket,
    keyfile='openssl/web1/httpd.key',
    certfile='openssl/web1/httpd.crt',
    #cert_reqs=ssl.CERT_REQUIRED,
    #ca_certs='openssl/cacert.pem',
    server_side=True,
    ssl_version=ssl.PROTOCOL_TLSv1)

傳送根證書 cacert.pem 到 local, 並改名為 cacert.crt
匯入憑證


2016年9月6日 星期二

SpeechSynthesisUtterance 無法說中文

之前參考 Speech Synthesis API 製作 語音學習站
發現其中 中文的發音 在部分電腦可以正常發音,有些則不行

之後參考 SpeechSynthesisUtteranceGetting Started with the Speech Synthesis API 修正


// Chrome loads voices asynchronously.
window.speechSynthesis.onvoiceschanged = function(e) {
  var synth = window.speechSynthesis;
  voices = synth.getVoices();
  var voice_1 = document.getElementById('voice_1');
  while (voice_1.options.length) {
    voice_1.remove(0);
  }
  var voice_2 = document.getElementById('voice_2');
  while (voice_2.options.length) {
    voice_2.remove(0);
  }
  voices.forEach(function(voice, i) {
  var opt1 = document.createElement("option");
  opt1.textContent = voice.name + ' (' + voice.lang + ")";
  opt1.setAttribute('data-lang', voice.lang);
  opt1.setAttribute('data-name', voice.name);
  if (voice.lang == "en-US") {
    opt1.selected = true;
  }
  voice_1.appendChild(opt1);
});


2015年10月22日 星期四

2015年2月4日 星期三

開啟 https,使用 openssl CA

建立CA私鑰
D:\EclipseAndroid\Web>openssl genrsa -out cakey.pem 2048
查看公鑰
D:\EclipseAndroid\Web>openssl rsa -in cakey.pem -pubout -text
生成自簽證書
D:\EclipseAndroid\Web>set OPENSSL_CONF=c:\Program Files (x86)\GnuWin32\share\openssl.cnf
D:\EclipseAndroid\Web>openssl req -new -x509 -key cakey.pem -out cacert.pem -days 3650
Loading 'screen' into random state - done
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:TW
State or Province Name (full name) [Some-State]:Taiwan
Locality Name (eg, city) []:Taichung
Organization Name (eg, company) [Internet Widgits Pty Ltd]:R&D
Organizational Unit Name (eg, section) []:Mark Chen
Common Name (eg, YOUR name) []:Mark Chen
Email Address []:ingrenn@yahoo.com.tw
D:\EclipseAndroid\Web>mkdir demoCA
D:\EclipseAndroid\Web>mkdir demoCA\private
D:\EclipseAndroid\Web>mkdir demoCA\newcerts
在 demoCA 目錄下建立文字檔 index.txt
在 demoCA 目錄下建立文字檔 serial,內容 "00"
D:\EclipseAndroid\Web>copy cakey.pem demoCA\private
D:\EclipseAndroid\Web>copy cacert.pem demoCA
建立給 tomcat 使用的私鑰
D:\EclipseAndroid\Web>openssl genrsa -out tomcat.key 1024
tomcat 客戶端生成證書簽屬請求
D:\EclipseAndroid\Web>openssl req -new -key tomcat.key -out tomcat.csr
Loading 'screen' into random state - done
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:TW
State or Province Name (full name) [Some-State]:Taiwan
Locality Name (eg, city) []:Taichung
Organization Name (eg, company) [Internet Widgits Pty Ltd]:R&D
Organizational Unit Name (eg, section) []:Mark Chen
Common Name (eg, YOUR name) []:localhost因為在本機使用,正式須如:www.domain.com
Email Address []:ingrenn@localhost

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:不要打密碼,不然會失敗
An optional company name []:
D:\EclipseAndroid\Web>openssl ca -in tomcat.csr -out tomcat.crt -days 3655
D:\EclipseAndroid\Web>openssl pkcs12 -export -in tomcat.crt -inkey tomcat.key -out tomcat.p12
Loading 'screen' into random state - done
Enter Export Password:在 tomcat 的 server.xml 設定中要用
Verifying - Enter Export Password:

在 tomcat 的 server.xml 設定中
<Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
  maxThreads="150" scheme="https" secure="true"
  clientAuth="false" sslProtocol="TLS"
  keystoreFile="D:\EclipseAndroid\Web\tomcat.p12"
  keystoreType="pkcs12" keystorePass="changit"
/>


開啟 IE /網際網路選項/內容/憑證/受信任的跟憑證授信單位/匯入 cacert.pem

如果要將 http 自動轉成 https,在 web.xml 的 <web-app> 中加入下列設定
<!-- Require HTTPS for everything except /img (favicon) and /css. -->
<security-constraint>
  <web-resource-collection>
    <web-resource-name>HTTPSOnly</web-resource-name>
    <url-pattern>/*</url-pattern>
  </web-resource-collection>
  <user-data-constraint>
    <transport-guarantee>CONFIDENTIAL</transport-guarantee>
  </user-data-constraint>
</security-constraint>
<security-constraint>
  <web-resource-collection>
    <web-resource-name>HTTPSOrHTTP</web-resource-name>
    <url-pattern>*.ico</url-pattern>
    <url-pattern>/img/*</url-pattern>
    <url-pattern>/css/*</url-pattern>
  </web-resource-collection>
  <user-data-constraint>
    <transport-guarantee>NONE</transport-guarantee>
  </user-data-constraint>
</security-constraint>


android 安裝證書
1. copy cakey.pem cakey.cer
2. 將 cakey.cer 證書放到 /storage/sdcard0/Download
3. 設定/安全性/從手機儲存空間安裝


開啟 https

在 命令提示字元下
>"c:\Program Files\Java\jre7\bin\keytool.exe" -genkeypair -alias tomcat -keyalg RSA -keystore keystore.pfx -storetype pkcs12
您的名字與姓氏為何?
  [localhost]:
您的組織單位名稱為何?
  [R&D]:
您的組織名稱為何?
  [Mark Chen]:
您所在的城市或地區名稱為何?
  [tw]:  Taichung
您所在的州及省份名稱為何?
  [taiwan]:
此單位的兩個字母國別代碼為何?
  [tw]:
CN=localhost, OU=R&D, O=Mark Chen, L=Taichung, ST=taiwan, C=tw 正確嗎?


在 tomcat 的 server.xml 中
    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
        maxThreads="150" scheme="https" secure="true"
        clientAuth="false" sslProtocol="TLS"
        keystoreFile="D:\EclipseAndroid\Web\keystore.pfx"
        keystoreType="pkcs12" keystorePass="mark1234"
        />

開啟 IE /網際網路選項/內容/憑證/個人/匯入 keystore.pfx


您的名字與姓氏為何?即是CN
其內容必須是網域名稱如 www.host.com.tw 或 localhost

使用 -storetype pkcs12 否則 IE 無法匯入憑證


2014年12月23日 星期二

Google API

錯誤訊息
{"responseData": null, "responseDetails": "Suspected Terms of Service Abuse. Please see http://code.google.com/apis/errors", "responseStatus": 403}

到此申請帳號
https://developers.google.com/custom-search/v1/using_rest?hl=zh-TW


https://script.google.com/macros/s/AKfycbwwz9O_uKzZtpd3RPkuZLbQkueQUsDYHaEFhmi7PNXvzv_UrFo/exec?id=1Gt9Fe1WbNBSe1pMzqF50Lv1HBAnq7C_Hwh0lfTWVumM

"http://translate.google.com.tw/translate_tts?" +
      "ie=UTF-8&q=" + text + "&tl=" + lang + "&total=1&idx=0" +
      //"ie=UTF-8&q=" + escape(text) + "&tl=" + lang + "&total=1&idx=0" +
      "&textlen=" + text.length;

2014年10月15日 星期三

語言學習站 IE11 也可以

<audio> 在 IE 真的不好用
還是舊的 <bgSound>
雖然 IE8 上的 ajax.responseText 一直是 undefined
但是 IE11 上成功了。

2014年10月8日 星期三

瀏覽器種類判斷


$(function () {
var Sys = {};
var ua = navigator.userAgent.toLowerCase();
var s;
// gecko for IE11
(s = ua.match(/rv:([\d.]+)\) like gecko/)) ? Sys.ie = s[1] :
(s = ua.match(/msie ([\d.]+)/)) ? Sys.ie = s[1] :
(s = ua.match(/firefox\/([\d.]+)/)) ? Sys.firefox = s[1] :
(s = ua.match(/chrome\/([\d.]+)/)) ? Sys.chrome = s[1] :
(s = ua.match(/opera.([\d.]+)/)) ? Sys.opera = s[1] :
(s = ua.match(/version\/([\d.]+).*safari/)) ? Sys.safari = s[1] : 0;

if (Sys.ie) $('span').text('IE: ' + Sys.ie);
if (Sys.firefox) $('span').text('Firefox: ' + Sys.firefox);
if (Sys.chrome) $('span').text('Chrome: ' + Sys.chrome);
if (Sys.opera) $('span').text('Opera: ' + Sys.opera);
if (Sys.safari) $('span').text('Safari: ' + Sys.safari);
});

2014年10月2日 星期四

網頁升級

replaceNode -> replaceChild

removeNode -> removeChild

event.srcElement -> event.target

<bgSound>還可以在 IE 上運作,Chrome 則要用 <audio>

iframe.style.pixelWidth -> iframe.style.width

<center> -> <div style="text-align:center;"> 和 <table style="margin:auto;">

document.all.name -> document.getElementsByName('name')[0]

if (event.keyCode == 13) {
  event.keyCode = 9; // 失效了
}
直接尋找下一個元件 focus()

table 內會自動加入無效的 space & enter

Grid.jsFixHeader // 失效了
不要在 TR 內設 style.position = "relative"
改在每個 TH 內設定, style.top 也是如此

showModalDialog() // 失效了

rtMethod.value = "parent.window.jsMethodRt";



2014年6月17日 星期二

英文學習站 忽然死了

經過查證

發出 request
https://googledrive.com/host/0B7u4moMmo8nDMDJuTmxSMGptUmc?ti=%u9673%u5E73%u82F1%u6587%u4E94%u4E0B_Unit1&id=1bXGGbmey3BTWtvZDdHLVwFHgEUNERXtzHSEucaBt6cs
回覆: status 301
轉成
https://079d23e82a287d32341893c3a6d0d7c6f9632316.googledrive.com/host/0B7u4moMmo8nDMDJuTmxSMGptUmc
此時掉了 query string

建立 EnglishClass.html,將課程列表放入
將 Google Drive 的目錄 share,在 share folder 內可以直接使用檔名

2014年5月20日 星期二

2014年5月14日 星期三

英文學習站 使用方式

  1. 用滑鼠點 英文字 會發音。
  2. 用滑鼠快點兩下 英文或中文字 會隱藏或顯示 英文或中文字。
  3. 點選第一列標頭的 中文 或 英文,會隱藏或顯示整欄的 英文或中文。
  4. 點選表格上方隻重排,會重新排列表格。
  5. 再輸入欄位填入英文後按 enter,會發出輸入之音,並檢查輸入英文是否正確。
正式發布 英文學習站

設計過程遇到一大堆的窟窿
本想解決一個,就發佈一篇網誌
但那是不可能的

除了可能根本無法完成 英文學習站 計畫
(當然也可將網誌視為失敗紀錄)
在解決問題的過程中,一關接著一關
整個腦袋想著各種的可能
實在是分不出精神來做這事
目前只能寫寫回憶錄了


  • Google 發音 時靈時不靈,尤其在 Google 的 blogger,後來發現 Google Drive 內的網頁也會,本機的網頁比較不會。直覺的反應就是 Cache,所以在 chrome 的 紀錄/清除瀏覽資料 中勾選 快取圖片和檔案,解決了時靈時不靈的狀況,變成本機正常,Google 內的都不正常。
  • 懷疑是 google 的 blogger 內的某一些 script 導致錯誤,所以將網頁移往 Google Drive。但還是一樣。
  • 利用 chrom 內 網頁中按滑鼠右鍵,選擇 檢查元素,切換 Network 頁簽,檢查網路傳輸的差異,發現不能發音是 Status canceled,利用 chrome://net-internals ,選擇 Events,發現 正不正常 的差異是,HTTP 協議 Header 中 Referer,本機正常 沒有 Referer,Google 內的網頁不正常 都有 Referer,推測是 Google 發現 Referer 來自 Google 本身,所以回覆了404 not found。
  • 本以為 ajax.setRequestHeader("Referer", ""); 能消除 Referer,發現安全性問題使得不能作用,隨後安裝 chrome 的擴充功能 Referer Control,就成功了,但是 IE 怎麼辦?之後又發現 https:// 到 http:// 也有安全性問題,不會傳送 Referer,所以將 https://translate.google.com.tw/translate_tts 改成 http://translate.google.com.tw/translate_tts 就完成了。
  • 雖然 chrome 成功,IE 居然不行,虧我還是從微軟的網站上找到的資料。試試看把 audio 藏在 iframe 吧!
  • 雖然 iframe 把 Referer 移除,但是裡面的 audio 移除了一半,不知為何 IE 連送三次 Request,第三次才移除 Refere_r,但還是不說話。
  • 網路上有人猜測,只要有 Referer,translate_tts 就不動作,害我還懷疑是 google 的 blogger 內的某一些 script 導致錯誤,大動干戈。
  • 最後放棄了,把 IE 獨立出來。
另一個問題是 Google Drive 內的網頁問題,因為一時懶惰,沒有看清說明,直接使用 share 的網址,如下 https://drive.google.com/file/d/0B7u4moMmo8nDOERrYlFDRm9NaUU 一直不成功,直到最後才發現要改成 https://googledrive.com/host/0B7u4moMmo8nDOERrYlFDRm9NaUU。