1
0
mirror of https://github.com/actix/examples synced 2025-06-28 18:00:37 +02:00

Restructure folders (#411)

This commit is contained in:
Daniel T. Rodrigues
2021-02-25 21:57:58 -03:00
committed by GitHub
parent 9db98162b2
commit c3407627d0
334 changed files with 127 additions and 120 deletions

View File

@ -0,0 +1,9 @@
[package]
name = "awc_https"
version = "0.1.0"
authors = ["dowwie <dkcdkg@gmail.com>"]
edition = "2018"
[dependencies]
actix-web = { version = "3", features = ["openssl"] }
openssl = "0.10.28"

View File

@ -0,0 +1,9 @@
The goal of this example is to show you how to use the actix-web client (awc)
for https related communication. As of actix-web 2.0.0, one must be very
careful about setting up https communication. **You could use the default
awc api without configuring ssl but performance will be severely diminished**.
This example downloads a 10MB image from wikipedia.
To run:
> curl http://localhost:3000 -o image.jpg

View File

@ -0,0 +1,42 @@
use actix_web::{
client::{Client, Connector},
web, App, HttpRequest, HttpResponse, HttpServer,
};
use openssl::ssl::{SslConnector, SslMethod};
async fn index(_req: HttpRequest) -> HttpResponse {
let builder = SslConnector::builder(SslMethod::tls()).unwrap();
let client = Client::builder()
.connector(Connector::new().ssl(builder.build()).finish())
.finish();
let now = std::time::Instant::now();
let payload =
client
.get("https://upload.wikimedia.org/wikipedia/commons/f/ff/Pizigani_1367_Chart_10MB.jpg")
.send()
.await
.unwrap()
.body()
.limit(20_000_000) // sets max allowable payload size
.await
.unwrap();
println!(
"awc time elapsed while reading bytes into memory: {} ms",
now.elapsed().as_millis()
);
HttpResponse::Ok().content_type("image/jpeg").body(payload)
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
let port = 3000;
HttpServer::new(|| App::new().service(web::resource("/").to(index)))
.bind(("0.0.0.0", port))?
.run()
.await
}

View File

@ -0,0 +1,10 @@
[package]
name = "actix-casbin-example"
version = "0.1.0"
authors = ["Chojan Shang <psiace@outlook.com>"]
edition = "2018"
[dependencies]
actix-web = "3"
casbin = "2"
loge = {version = "0.4", default-features = false, features = ["colored", "chrono"]}

26
security/casbin/README.md Normal file
View File

@ -0,0 +1,26 @@
# Casbin
Basic integration of [Casbin-RS](https://github.com/casbin/casbin-rs) with [RBAC](https://en.wikipedia.org/wiki/Role-based_access_control) for Actix web.
## Usage
```sh
cd examples/casbin
```
Modify the files in the `rbac` directory and the code in the `src` directory as required.
## Running Server
```sh
cd examples/casbin
cargo run (or ``cargo watch -x run``)
# Started http server: 127.0.0.1:8080
```
In this example, you can get the the successful result at `http://localhost:8080/success` (accessible) and the failed result at `http://localhost:8080/fail` (inaccessible, `ERR_EMPTY_RESPONSE`).
## Others
- For more related examples of [Casbin-RS](https://github.com/casbin/casbin-rs): <https://github.com/casbin-rs/examples>

View File

@ -0,0 +1,14 @@
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act

View File

@ -0,0 +1,5 @@
p, alice, data1, read
p, bob, data2, write
p, data2_admin, data2, read
p, data2_admin, data2, write
g, alice, data2_admin
1 p, alice, data1, read
2 p, bob, data2, write
3 p, data2_admin, data2, read
4 p, data2_admin, data2, write
5 g, alice, data2_admin

View File

@ -0,0 +1,55 @@
use casbin::{CoreApi, DefaultModel, Enforcer, FileAdapter, RbacApi};
use std::io;
use std::sync::RwLock;
use actix_web::{middleware, web, App, HttpRequest, HttpResponse, HttpServer};
/// simple handle
async fn success(
enforcer: web::Data<RwLock<Enforcer>>,
req: HttpRequest,
) -> HttpResponse {
let mut e = enforcer.write().unwrap();
println!("{:?}", req);
assert_eq!(vec!["data2_admin"], e.get_roles_for_user("alice", None));
HttpResponse::Ok().body("Success: alice is data2_admin.")
}
async fn fail(enforcer: web::Data<RwLock<Enforcer>>, req: HttpRequest) -> HttpResponse {
let mut e = enforcer.write().unwrap();
println!("{:?}", req);
assert_eq!(vec!["data1_admin"], e.get_roles_for_user("alice", None));
HttpResponse::Ok().body("Fail: alice is not data1_admin.") // In fact, it can't be displayed.
}
#[actix_web::main]
async fn main() -> io::Result<()> {
std::env::set_var("RUST_LOG", "info");
std::env::set_var("LOGE_FORMAT", "target");
loge::init();
let model = DefaultModel::from_file("rbac/rbac_model.conf")
.await
.unwrap();
let adapter = FileAdapter::new("rbac/rbac_policy.csv");
let e = Enforcer::new(model, adapter).await.unwrap();
let e = web::Data::new(RwLock::new(e)); // wrap enforcer into actix-state
//move is necessary to give closure below ownership of counter
HttpServer::new(move || {
App::new()
.app_data(e.clone()) // <- create app with shared state
// enable logger
.wrap(middleware::Logger::default())
// register simple handler, handle all methods
.service(web::resource("/success").to(success))
.service(web::resource("/fail").to(fail))
})
.bind("127.0.0.1:8080")?
.run()
.await
}

View File

@ -0,0 +1,10 @@
[package]
name = "openssl-example"
version = "0.2.0"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
edition = "2018"
[dependencies]
actix-web = { version = "3", features = ["openssl"] }
env_logger = "0.8"
openssl = "0.10"

View File

@ -0,0 +1,34 @@
# tls example
## Usage
### Certificate
We put the self-signed certificate in this direcotry as an example
but your browser would complain that it isn't secure.
So we recommend to use [`mkcert`] to trust it. To use local CA, you should run:
```bash
mkcert -install
```
If you want to generate your own cert/private key file, then run:
```bash
mkcert 127.0.0.1
```
[`mkcert`]: https://github.com/FiloSottile/mkcert
### server
```bash
cd examples/openssl
cargo run (or ``cargo watch -x run``)
# Started http server: 127.0.0.1:8443
```
### web client
- curl: ``curl -v https://127.0.0.1:8443/index.html --compressed -k``
- browser: [https://127.0.0.1:8443/index.html](https://127.0.0.1:8443/index.html)

24
security/openssl/cert.pem Normal file
View File

@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIEDDCCAnSgAwIBAgIQLu2TV80hCgYgZe18ovEhmzANBgkqhkiG9w0BAQsFADBZ
MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExFzAVBgNVBAsMDmh1eXV1
bWlAcmlyaWthMR4wHAYDVQQDDBVta2NlcnQgaHV5dXVtaUByaXJpa2EwHhcNMTkw
NjAxMDAwMDAwWhcNMzAwNTE5MDM0MjI2WjBCMScwJQYDVQQKEx5ta2NlcnQgZGV2
ZWxvcG1lbnQgY2VydGlmaWNhdGUxFzAVBgNVBAsMDmh1eXV1bWlAcmlyaWthMIIB
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5fRUIbEv2DjBmK7+syGVvh3I
FWDlVjU9N7ypxauQbXPHAzpATzghLnpm5CqQFoTnJwA4//A85775djcVlsAUqen2
ZYi+4jTYeuRLrAJ0dkrUS8/7+T0fGzGZ8obCsII5iSE2BMS7AxbqlQtClDdkNwcK
rCuzrmIyMA8Bc2V231xIgcWFJ7en8OaZJRlYYK7kp2cJ8g0PbPnVq+9TAfFYcKEy
FWqJsYYY36bLbWyqYXGMOtAh2bhy+YGYL3Jhk+cw7iMCjye4FbDAIQzt9cH1KGGM
2VWZFiwn6VJquX1Z+n9KAhfzxuzYQHSrlJ+Rt++gezpTtNw8q15Ko78oiu7CLQID
AQABo2cwZTAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYD
VR0TAQH/BAIwADAfBgNVHSMEGDAWgBSljCjB0QNrBG+8BV3nFnUyBn54jjAPBgNV
HREECDAGhwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBgQAsUrfA8deCaHYy7wB1jEVK
pNZKRNcDKxqr/PXJQlfwwlq1qZTBzloMNTzfVBRkn/I7y+Bj/b1uYFmjQoQ3qG9s
tIXFCYOop1cLltmWXC479/UtbEmhz0t+mzK0MFkLhxtbKqwvMGbcGGDFI/2/MGZN
XFZXL1bclFieZxO5ePEkZSDkPcWvh9uYWCp8r7H6aAd/iwH4lDxfajyhDneRmd/v
Mq0PgqTZhVHOP7JdVNA+6cewROyPL7ElLs66ujE9hsRvs6eXLjgLZrHOZShnoQxK
JJv8UfoE90FX1uDt9w9i3raig/O3oePNkU263kJlR+J1rdVdYV+pCCb7L4Vk+1l3
S4VFVGVHN8x35dISCJwZrtnqPlfpCiLjtEJOu1zJUEY2Q0n7Km3z3zQcs6iCeOQi
O9MVJ4aiALdNvyCG7lL4+AJ/kWbwHFM6wOAKSrkpZ20msMuEgIlhCOi8PgYlKb+b
V/lV6IJPVrAOOclgcvtfZ/LdsTxn15yLIieqgR0Lf/s=
-----END CERTIFICATE-----

28
security/openssl/key.pem Normal file
View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDl9FQhsS/YOMGY
rv6zIZW+HcgVYOVWNT03vKnFq5Btc8cDOkBPOCEuembkKpAWhOcnADj/8Dznvvl2
NxWWwBSp6fZliL7iNNh65EusAnR2StRLz/v5PR8bMZnyhsKwgjmJITYExLsDFuqV
C0KUN2Q3BwqsK7OuYjIwDwFzZXbfXEiBxYUnt6fw5pklGVhgruSnZwnyDQ9s+dWr
71MB8VhwoTIVaomxhhjfpsttbKphcYw60CHZuHL5gZgvcmGT5zDuIwKPJ7gVsMAh
DO31wfUoYYzZVZkWLCfpUmq5fVn6f0oCF/PG7NhAdKuUn5G376B7OlO03DyrXkqj
vyiK7sItAgMBAAECggEBAIabZmAukz4zwwe4cDm1kC0wy73P8Y9sLMCivJKMYkff
vQBjqd91kN7fIbmwPJYiCBlpZPRU0aIqxWZwyj9rgu0Pmn9G884AdzRAzRcMfNX9
6ZXTUsFMCRhnCaHRRsgCAuIFwdQ6wOoHERxb8gZHAm+/vHyaPFz4+D3vmr7NBy+p
fgpdDCGwkltKI73efk6H4oAeyztDwNev/TZ3Y+O3UKuAUfVReBX0us/lYgEf/KXV
USd7envxACy+PDcqmn/HL6IUnbrc1zB92dmSSUUtLjOz//z1zM05ME/E2keMQwsW
7LDen0Lm0Nh6AcOCxmnN4u0lJ3nWzU7PsHJKY/LznPUCgYEA5kQq/AG6LlL9Iu1E
Y55AB1rkvseof41liaqXVccB5tr55IF75d0wPd6jF04W+x6LwmL6EUYPRGkkOdHE
raz9CDE3a7hWbAghxIwLrI1s+faT5aaHG9o6mTeDyfgEEoBg8X2nQHQJPayDJZcW
kiXQyHEtj/G4m/Y+WDFXastZz8MCgYEA/6c8+cI3Slvg3CZLG9f6rdAlrOSIQynF
muXyVeUaxrU0OPC9H3WEwWv7n4adQU2g0L6TBTdlOOiv5SPIsOPQVN2JZVdxwg0V
n5+7/WRrI9rAXnmu1x0q1e/TZ9Msggmrn5SdHaEfuug4DnHv4nct356joDwYB2i3
xYl+yCSMd08CgYEAqduvOaasiG9/e7w6rqGV6dcK1hDCIxVSyXKloAjlRj5SCFXb
53x6kakh9ZcNLMEjp4kLnqJnsLc+mcg7pUHuhZSIpVWdqqN1BV+pXOgWc22JO+bT
05/vigaBmQLzPhKlcH6YWds+1dfkBl6lr7llgfa6/Wv6GlJTOwtqyMSow7ECgYEA
zGQ8j8ICymRihh/ndL9cH5KGTI/5kRjYb1rgQGQG4E8HDW8LBRfDp5BZf9Tz7L3P
kJSMnmMHflQqLJxLW4EHkpH7wxYCUQ589z2R4qhiMCw4GFBYxIsBMEGpVxyyPNTW
baM3afTjlV8LUiEtlHWMK3h9gSIKZAIIytl+jy0JUGkCgYA3wrpcG3wgXeuEtoie
ve/kFS5JRaOeV/9OLE2JGaGaumPlN0L14kCVvb6uqLa/P88BwBUxvGQ7FDBdh4sk
ypuSe9ZPCNDgnsbnfM8QgFqIW6MDdizLtj7no1SKeaUU3JWWc0kH2KWMw/sYZ7ec
0tcEInxEd7FbssGfMqF9fQtnNw==
-----END PRIVATE KEY-----

View File

@ -0,0 +1,44 @@
use std::io;
use actix_web::{middleware, web, App, Error, HttpRequest, HttpResponse, HttpServer};
use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod};
/// simple handle
async fn index(req: HttpRequest) -> Result<HttpResponse, Error> {
println!("{:?}", req);
Ok(HttpResponse::Ok()
.content_type("text/plain")
.body("Welcome!"))
}
#[actix_web::main]
async fn main() -> io::Result<()> {
std::env::set_var("RUST_LOG", "actix_web=debug");
env_logger::init();
println!("Started http server: 127.0.0.1:8443");
// load ssl keys
let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
builder
.set_private_key_file("key.pem", SslFiletype::PEM)
.unwrap();
builder.set_certificate_chain_file("cert.pem").unwrap();
HttpServer::new(|| {
App::new()
// enable logger
.wrap(middleware::Logger::default())
// register simple handler, handle all methods
.service(web::resource("/index.html").to(index))
// with path parameters
.service(web::resource("/").route(web::get().to(|| {
HttpResponse::Found()
.header("LOCATION", "/index.html")
.finish()
})))
})
.bind_openssl("127.0.0.1:8443", builder)?
.run()
.await
}

View File

@ -0,0 +1,12 @@
[package]
name = "rustls-client-cert"
version = "1.0.0"
authors = ["Rob Ede <robjtede@icloud.com>"]
edition = "2018"
[dependencies]
actix-tls = "2"
actix-web = { version = "3.2", features = ["rustls"] }
env_logger = "0.8"
log = "0.4"
rustls = "0.18"

View File

@ -0,0 +1,34 @@
# Access Client Certificate (via Rustls)
## Usage
### Certificate
All the self-signed certificate are in the ./certs directory, including the CA certificate
generated by [`mkcert`] that was used to create the server and client certs.
### Server
```sh
cd examples/rustls-client-cert
cargo run
```
The server runs HTTP on port 8080 and HTTPS on port 8443.
### Providing Client Cert
Using [HTTPie]:
```sh
# `--verify=false` used because HTTPie doesn't have an option to provide the CA cert
http https://127.0.0.1:8443/ --verify=false --cert=certs/client-cert.pem --cert-key=certs/client-key.pem
```
Using [cURL]:
```sh
curl https://127.0.0.1:8443/ --cacert certs/rootCA.pem --cert certs/client-cert.pem --key certs/client-key.pem
```
[`mkcert`]: https://github.com/FiloSottile/mkcert
[cURL]: https://curl.haxx.se/
[HTTPie]: https://httpie.org/

View File

@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEVDCCArygAwIBAgIRAOAgy58Y3ViVpV9G8DTyKzMwDQYJKoZIhvcNAQELBQAw
bTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSEwHwYDVQQLDBhyb2JA
c29tYnJhLng1Mi5kZXYgKFJvYikxKDAmBgNVBAMMH21rY2VydCByb2JAc29tYnJh
Lng1Mi5kZXYgKFJvYikwHhcNMTkwNjAxMDAwMDAwWhcNMzAxMDI1MTczODMxWjBM
MScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxvcG1lbnQgY2VydGlmaWNhdGUxITAfBgNV
BAsMGHJvYkBzb21icmEueDUyLmRldiAoUm9iKTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAJsp9QFEpfEWFB3CyFTA2Rv2tUMwnpQcDtiB1hwH03EYcMlG
pEkMh1tPTK8WZo2igMJrBtP2Vf2AN0/hmFWUZV1ZEUUNXXW0QD2mHS8Rgz7nAgmq
V5XvmLLeeo2vMdw1B2qsRxCPTjbInDsZsBqv2GyXWo5/9o3PD32h4LNk3w0VyA47
f/jdpMWlcIXQoyJJV1U1FPLf92xYZvWc9Vf/+K6mStESEpoFll+b4uqjPpwrEz9Q
KBY4eyXwhGCrjQC0+jJFNlIcbV5FgQSYd4DVMcw6SWdMeV/+VtQs+JQrENjNB3am
nJ5xpoZ7mmNDOkWg4zvoYRL6o7LtqT+8EXptzMMCAwEAAaOBjzCBjDAOBgNVHQ8B
Af8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMAwGA1UdEwEB
/wQCMAAwHwYDVR0jBBgwFoAUfpWkO5lYpQJz4omoVdVzuuZnn80wLAYDVR0RBCUw
I4IJbG9jYWxob3N0hwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEB
CwUAA4IBgQB8ulsrStRha8SRxoPRlTNIb9WMjNl5KdZF+ePpUctBX0lFmxqn0upu
l3BoZkhMrpPRRcGlDPImuL7tfxk/IuTA6S1AEQtEHCC8WyZbq3RODPzVY6J/IOUv
H2ZwZYo0c714FyNx8igBpVSjHT6yCIeQkSQlTXsWxddToSeKYvXg8VI+M5L0DH1Y
jRb2u3GpMPdLhMqGNZPcwbLkVyMe5aj4hx334fa3uLf/CK6/5ev4+ozSNz3Qr8S7
iPE8WXrny/qEJmTEme7eq6K/QPTC9ly3j+5Ms3Uepnk0Jez9/ksOrlbYrWXhwD0P
Nwvn3HtiYy8q1HwRw5U+LMNyh6lIyfJUsu2tRmYz1fiH74tMDFb2pjDpcmvgaSJY
eSwKksOiX1No6K980ECEkCX9iQFwD5edTCnD2lz+AVGDzZPkY/551Ohl+KMh/mFG
uZNtgjUeMh0btfc9D+PLLLHjpSMVkRMEEmtm/Zi2nKeVCAdIomFfk+EFIEOdaMyk
SUZMUFzBP+4=
-----END CERTIFICATE-----

View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCbKfUBRKXxFhQd
wshUwNkb9rVDMJ6UHA7YgdYcB9NxGHDJRqRJDIdbT0yvFmaNooDCawbT9lX9gDdP
4ZhVlGVdWRFFDV11tEA9ph0vEYM+5wIJqleV75iy3nqNrzHcNQdqrEcQj042yJw7
GbAar9hsl1qOf/aNzw99oeCzZN8NFcgOO3/43aTFpXCF0KMiSVdVNRTy3/dsWGb1
nPVX//iupkrREhKaBZZfm+Lqoz6cKxM/UCgWOHsl8IRgq40AtPoyRTZSHG1eRYEE
mHeA1THMOklnTHlf/lbULPiUKxDYzQd2ppyecaaGe5pjQzpFoOM76GES+qOy7ak/
vBF6bczDAgMBAAECggEAOAzN/mlH8HDjT2TfbQ5E3z8dd2oGvsXr7vXn3DRPgxkr
FOo5ylGGS8u3jb/vx9Yd4R08WDEyGuLIGEkL+E4k17Wm8WTEkBJO6nYpMKmI2Z4l
NEyeWwE0DdkkOC5DOqLFTRlyil7aCBwro4XCAcHn0kJSagt7ivpzRBTH0MXtdRIL
L37nOInga2puSeHLOGj9W1Q0AX0EIiecqLPpCLmz+xotlevFBmlQ4iFT7xkoKH+s
NeqWEd0HTNYkYQZtZ9husDzNK4x59MKUYS1oWB8A8JKu5E4ovdb6R6LjyN/Y5lNl
3Z4Mg2DJ4iBN4DRnEBwiY8bdeqYboMNNyAbCU+nPYQKBgQDLP0lEYsdcSNF5Uv0c
fe5pUvAzyTUzVhP7LLOk2jdRxs85MNbYJkays40rROqm2+StSFgih3NpA9D1pl7f
ucJABlK9OkTtOshFSR6Q+0NomKLHhBGvYpouC2tIHjGsE/KjiQa4I1Pia72xpIWT
QK3isM2c11924RqdoJ0mpBKpOwKBgQDDb8k4U512u+exVvFQ8JEbro4oy4jsc74L
BZG6PbHZcIADKANmB15ahN3tCkDwJQ8iJYX7bmzn+8jR2HtznchgJwWN9aGtEP4C
qTmmyrJd09pMMs5W4/BucD7wJ7s32PwVUwj0nvW+BHE4LQk5td4a3VE1wj1EZ8bR
+JCK081yGQKBgQCG1vKtuvbWY70NR6CCwY1lNNAFG0z/RPE2pz57dQZUa5hZMeyn
NCWdMv/KIAupLaN1ztQh/Ej198Eu5/RzaxLTVR6ZScomtOPfC5aKyxe6keEUiqsM
91agi5TeIKIFrqpAEo1xpoZlZeNQsnyn57Y0+eU/U6eS/96fisoXs6xptwKBgQCy
loDqnsXCTR0AmbE0RFBlWlH/h1Ycs/tSeQlchanyR3JC8BqC7nLTBp0BUaBbkZHN
ozpWsuaD6jntQAQ3d1Q2QRI7Ud0ml+N1rQvIlWr+gGv3u2mATxRS5vEsZTIYa4iX
N+R0HJn0xHxtWAIZIU7Pf7QJCvEPhEFTd+8lXTxcaQKBgG5d4vG5AyYXuiKKmm+d
MM4PPMJNw3+u5G50hgI4D/1WlirP9m6HIpFouNNGoggxpBBUeokIBPsXbq/fnkq2
uZmkAkWZeMeWHbI0lHSsE98ZTQHg36dNJ9hRHVRJ9PA2/YTSnr3WzDaaA1v5aoTv
xJyGdLlEy+RiIZCPk9RKtVc4
-----END PRIVATE KEY-----

View File

@ -0,0 +1,40 @@
-----BEGIN PRIVATE KEY-----
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
nctls65dJGslcxgwD6O1rA==
-----END PRIVATE KEY-----

View File

@ -0,0 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIEqTCCAxGgAwIBAgIQL82W4ilLJ4cs8zMbhJ+7aTANBgkqhkiG9w0BAQsFADBt
MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExITAfBgNVBAsMGHJvYkBz
b21icmEueDUyLmRldiAoUm9iKTEoMCYGA1UEAwwfbWtjZXJ0IHJvYkBzb21icmEu
eDUyLmRldiAoUm9iKTAeFw0yMDEwMjUxNzIyMzlaFw0zMDEwMjUxNjIyMzlaMG0x
HjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTEhMB8GA1UECwwYcm9iQHNv
bWJyYS54NTIuZGV2IChSb2IpMSgwJgYDVQQDDB9ta2NlcnQgcm9iQHNvbWJyYS54
NTIuZGV2IChSb2IpMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAq8NA
5lGYNYUxCknpFKQ14RBJlbEgjcfHIi8hp9TobzUigyOQoZ9W50WmChRuuAO/fXIG
i8ioejoteNPVbJj7ggMKx13256cvDKVR79NKeoHBSYUUjs2NyZZ3zPUeUe0tXPHR
J4RMWLmpYKdI6NCYjDX6ouCIeh6sinTOSV+0dbnfHvFGESFpUeiUdsnCRorsa/oB
n+hIn5dvftuxSDYDbADsSLDqhxY4xsQJKP00uNysLP0vewBqTSULNeHMNf0Yhpiy
ot/tbcRqQAzSzRIvWeCgw0GcjqPW27/p/x/4Sh3XzjT6w1xVtF7ZniW37M4gQktN
HnMWVgceqo0TaCwo+B37XJa/fBRH0x8HnMda1JeZ7X8/Szyc7YEa1M6ZkKONeCEg
C7+8jp/aTM/0DuvIIhxHwK/9PGvWYDFJny2Jf8pq1jJ66Gr0uWxRJHobf2kB+aF3
KUs5nK49Kw+TmZcB+SbU256e2wPhusxqxXnYi9WjdIyCqF3B1hYxEiaRiFRTAgMB
AAGjRTBDMA4GA1UdDwEB/wQEAwICBDASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1Ud
DgQWBBR+laQ7mVilAnPiiahV1XO65mefzTANBgkqhkiG9w0BAQsFAAOCAYEAe3A5
5z5JWHSXEcQI/LstAVJfiloehyhvYgcNpImlsm5A41VzMd1iWdpLY+WSKWjHKFs0
u5Id+sGEZRHBicYDts0azH3Sklj0FrNrpRdvf8jJuMvVC1EoUFijG+V/RdL14bxq
kyp5dtxVcvtvULT+ID5vSVYBwGOBp36Fg5Qs4QOuSPkVGwjaEdJvzqb1XDLncsve
ap6ALzwOXUsN8Icrq4/GlVDX11rOnfWhNQRiWKJtin4vzxL002rPWwSsekcuLEFQ
NCBYaBBDlp4fLh2XVuB7xvKXTPm8K9hIxrTBEh8kj8p5p95DOTWpLgXuBcdXmNDV
/4NBzsWwuO3I7/ilHbH+gEsM390p056Bmv2cF0bWb+xT2vyNymhmSCn77QEmcsOF
LDqsjDc7JsQGUVIAgtM50md/QvaXxTVoAMXtSWeyK8QsC2syZqWlXiYkrwYjp+KI
6jX4EpLwKdQOzZdjgnIZvG94o5lR8cPyZlaUKVunOTvAXiT3AWeBppCk6SEH
-----END CERTIFICATE-----

View File

@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIESjCCArKgAwIBAgIRAKNTHdWsrKKCpKt19C/sI4UwDQYJKoZIhvcNAQELBQAw
bTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMSEwHwYDVQQLDBhyb2JA
c29tYnJhLng1Mi5kZXYgKFJvYikxKDAmBgNVBAMMH21rY2VydCByb2JAc29tYnJh
Lng1Mi5kZXYgKFJvYikwHhcNMTkwNjAxMDAwMDAwWhcNMzAxMDI1MTczODM4WjBM
MScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxvcG1lbnQgY2VydGlmaWNhdGUxITAfBgNV
BAsMGHJvYkBzb21icmEueDUyLmRldiAoUm9iKTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBANDv0oRupAGtAl9ZZTeTwdToYh/Gtaj3bAyhQQz+dQ5GzLS3
+Zvo3daepwnoNABoxuPwptb/jJ6Ec8rdvUiJkKb+jAuZ0vSuEqPTcgvbnqsV+7UT
8WleCUnOIY6FB+uTaLEptu5k+Pf7i3m1RqW1gRVlYcHsLuv3NBQW0bz+XUZvcirW
KVCxz2ex2aFzWXrAZEuOwMX+x+Wicd4tRfcio4mOI+jCRCsbwW0TsyWStrimcbl0
ldbRi8DeADf3VPQCMYmcJARYsTfRwK75OFMgmD0GTi8WURWQCbTJnwzop7Famno0
/I/Ef65Dngleb6HwG91EtEVU7QHqSXlUK41Au9kCAwEAAaOBhTCBgjAOBgNVHQ8B
Af8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADAfBgNV
HSMEGDAWgBR+laQ7mVilAnPiiahV1XO65mefzTAsBgNVHREEJTAjgglsb2NhbGhv
c3SHBH8AAAGHEAAAAAAAAAAAAAAAAAAAAAEwDQYJKoZIhvcNAQELBQADggGBAJJ0
7oDkVmdB/P0PX0vIn+CPmiE8IrO8stItOGlVRy9TDWFRdMpY13BOjlNY2efNU2Tz
or+lyfV7D8PiCk5q3e8sLtOlIAT32IRIrGXl5E4q7zDnOckQjZIUZwSFAFVygy4F
rPgJCS9uqz9vz086SyRD0krTM5u9yMAvG2uJLEk5oaVWAKdDRplStmMx7QQHMZ4G
iNYMDpj4dU4gkrvZeC+JKwjbSJ3hje8CZCA1atzz/5WWEt2D8Yf9tw27T/hinrMi
rrjPpEcA6C8wvHxqYpiptQC1FF5vaUyRqjF+irHgQdNUCE0nJSwAsIDW0TDiVGDD
OJKs6EYuzJ8OcWw6IFx8YNvdxZJSr8SaavrH76myHieTkqhWvjSQERUw71iUwe0q
5Nev+J2N9U7oZBTCIsD/qKOQTD9mRjJpYLnXNqEyJhzRgCA5+TQIXbTa10eo9Svg
CTkqxsixmdTKD8ZIlUPhLI9ehr0Spbt+2Xh3yAtlSrfAt5p2hgVCoxalEwWpwA==
-----END CERTIFICATE-----

View File

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDQ79KEbqQBrQJf
WWU3k8HU6GIfxrWo92wMoUEM/nUORsy0t/mb6N3WnqcJ6DQAaMbj8KbW/4yehHPK
3b1IiZCm/owLmdL0rhKj03IL256rFfu1E/FpXglJziGOhQfrk2ixKbbuZPj3+4t5
tUaltYEVZWHB7C7r9zQUFtG8/l1Gb3Iq1ilQsc9nsdmhc1l6wGRLjsDF/sflonHe
LUX3IqOJjiPowkQrG8FtE7Mlkra4pnG5dJXW0YvA3gA391T0AjGJnCQEWLE30cCu
+ThTIJg9Bk4vFlEVkAm0yZ8M6KexWpp6NPyPxH+uQ54JXm+h8BvdRLRFVO0B6kl5
VCuNQLvZAgMBAAECggEAZ8PzZVodkcd+uiQHpMZ5KWgP84AYkEXxH4SmbfGh6Ok4
mTgVe1z3b7NzefQcf2eJ/4JxGa3pBID7kPD3JKNNd+JLYyeOIX6iO0K0DTeRYZ6V
V6UD7DSLoGADQmjHOjQHdpUlCNiU3XPMHTHuWDYAWcPz/P9zfjVTY/bBS394i5W/
nFLHMEGD/9KETUm2Wdmu+84fhAg+gSbDOHKOmrqiRoSmBInfUEjTL22gU1hPkjWY
17i9veMGVPQeA89XYmFavgWIMHwiOD0Fom2y26OIDWDXAJf7oOoONElWF2OjiSAa
7IHl8EED/aDIt9Xyv8J9qXzkAtLPXO8vFG2Uq0/BQQKBgQD1MlCsnMVf3dck8yg6
YwFkFHZxnFBzBPwuDoMD2OBIZcrwcBhUQo0u8M0NohgjvBB7XUrW+/5ucF9BaecC
3Rz/JwPk7oPafYVbEFGv+CeGJFKL/lq7NwF62N7EYo3N2ijYjGYiZFmxgOVEfzSd
WRSH+b6Q923lEpWoFaeFww+5HQKBgQDaJIRTr1stXXFXVj/ETJG4uT3I7qlfR7zp
/t/YHX6QnV5dFdBCEXSW41YoqvUn12Ox28nvQMDFWVkQGfAELYqkf/ozBQ9d6ee8
3bU9V14YWaGSK1RT83cgWUtDnUjtLuk9MG+5x3EQcfq5ng6ud+Hr8ut+gz0PbLcK
gR3uTQkM7QKBgENUSarccaZdeFKBIq7FuQAOTmfsEHtFBypuebN4vj2jFhLn9QZO
MA6PuP7hX9eQMMZvW7mlALy6xq1jszeqF+hIgl0+0Z4Rkajr1kKH1fKTzsb6VVfL
RvDA1IsAtQetvEGabAFNpQOE7W/drkj2yRh9j8Km7tpUPBwnthSY95xRAoGAL5uu
oZDwxjrRhK0XJ6FKYFVVTagAoQHIEg2FDuaI+8jMkmYzWGf02QVuhVuiO3q/kE6W
iLfKGogAbwoqHs9Npc8kbMQa8XUeFVMRvfx2VbwiDgOU2OmWwyGZ0nzeMJ1/W9JZ
X+NOIretb5s2Ow+A5/zRNoAv8FDatdkuDhcT9ZUCgYBtEI9pmWYXxGfaVQErJcsS
3a8PU875sE06DiEcvooljcLp6dCmGocRQOGpSXfy3zjX4F/HZjDK+GKPg2bCirKr
nRPWf0t3DSeSyDINj+a0fg4KvYR4FcocJDzTFJh/9CrtNktqwHAqrQUSokBbW8n6
Kj/AYLWOIXATfCrOgdoAAg==
-----END PRIVATE KEY-----

View File

@ -0,0 +1,105 @@
//! This example shows how to use `actix_web::HttpServer::on_connect` to access client certificates
//! pass them to a handler through request-local data.
use std::{any::Any, env, fs::File, io::BufReader, net::SocketAddr};
use actix_tls::rustls::{ServerConfig, TlsStream};
use actix_web::{
dev::Extensions, rt::net::TcpStream, web, App, HttpResponse, HttpServer, Responder,
};
use log::info;
use rustls::{
internal::pemfile::{certs, pkcs8_private_keys},
AllowAnyAnonymousOrAuthenticatedClient, Certificate, RootCertStore, Session,
};
const CA_CERT: &str = "certs/rootCA.pem";
const SERVER_CERT: &str = "certs/server-cert.pem";
const SERVER_KEY: &str = "certs/server-key.pem";
#[derive(Debug, Clone)]
struct ConnectionInfo {
bind: SocketAddr,
peer: SocketAddr,
ttl: Option<u32>,
}
async fn route_whoami(
conn_info: web::ReqData<ConnectionInfo>,
client_cert: Option<web::ReqData<Certificate>>,
) -> impl Responder {
if let Some(cert) = client_cert {
HttpResponse::Ok().body(format!("{:?}\n\n{:?}", &conn_info, &cert))
} else {
HttpResponse::Unauthorized().body("No client certificate provided.")
}
}
fn get_client_cert(connection: &dyn Any, data: &mut Extensions) {
if let Some(tls_socket) = connection.downcast_ref::<TlsStream<TcpStream>>() {
info!("TLS on_connect");
let (socket, tls_session) = tls_socket.get_ref();
data.insert(ConnectionInfo {
bind: socket.local_addr().unwrap(),
peer: socket.peer_addr().unwrap(),
ttl: socket.ttl().ok(),
});
if let Some(mut certs) = tls_session.get_peer_certificates() {
info!("client certificate found");
// insert a `rustls::Certificate` into request data
data.insert(certs.pop().unwrap());
}
} else if let Some(socket) = connection.downcast_ref::<TcpStream>() {
info!("plaintext on_connect");
data.insert(ConnectionInfo {
bind: socket.local_addr().unwrap(),
peer: socket.peer_addr().unwrap(),
ttl: socket.ttl().ok(),
});
} else {
unreachable!("socket should be TLS or plaintext");
}
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
if env::var("RUST_LOG").is_err() {
env::set_var("RUST_LOG", "info");
}
env_logger::init();
let mut cert_store = RootCertStore::empty();
// import CA cert
let ca_cert = &mut BufReader::new(File::open(CA_CERT)?);
cert_store
.add_pem_file(ca_cert)
.expect("root CA not added to store");
// set up client authentication requirements
let client_auth = AllowAnyAnonymousOrAuthenticatedClient::new(cert_store);
let mut config = ServerConfig::new(client_auth);
// import server cert and key
let cert_file = &mut BufReader::new(File::open(SERVER_CERT)?);
let key_file = &mut BufReader::new(File::open(SERVER_KEY)?);
let cert_chain = certs(cert_file).unwrap();
let mut keys = pkcs8_private_keys(key_file).unwrap();
config.set_single_cert(cert_chain, keys.remove(0)).unwrap();
// start server
HttpServer::new(|| App::new().default_service(web::to(route_whoami)))
.on_connect(get_client_cert)
.bind(("localhost", 8080))?
.bind_rustls(("localhost", 8443), config)?
.workers(1)
.run()
.await
}

View File

@ -0,0 +1,15 @@
[package]
name = "rustls-example"
version = "1.0.0"
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
edition = "2018"
[[bin]]
name = "rustls-server"
path = "src/main.rs"
[dependencies]
env_logger = "0.8"
rustls = "0.18"
actix-web = { version = "3", features = ["rustls"] }
actix-files = "0.3"

40
security/rustls/README.md Normal file
View File

@ -0,0 +1,40 @@
# TLS / HTTPS (via Rustls)
## Usage
### Certificate
We put the self-signed certificate in this directory as an example
but your browser would complain that it isn't secure.
So we recommend to use [`mkcert`] to trust it. To use local CA, you should run:
```bash
mkcert -install
```
If you want to generate your own cert/private key file, then run:
```bash
mkcert 127.0.0.1 localhost
```
For `rsa` keys use `rsa_private_keys` function instead `pkcs8_private_keys`
```
let mut keys = pkcs8_private_keys(key_file).unwrap(); // pkcs8
let mut keys = rsa_private_keys(key_file).unwrap(); // rsa
```
[`mkcert`]: https://github.com/FiloSottile/mkcert
### server
```bash
cd examples/rustls
cargo run (or ``cargo watch -x run``)
# Started http server: 127.0.0.1:8443
```
### web client
- curl: ``curl -v https://127.0.0.1:8443/index.html --compressed -k``
- browser: [https://127.0.0.1:8443/index.html](https://127.0.0.1:8443/index.html)

24
security/rustls/cert.pem Normal file
View File

@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIEDDCCAnSgAwIBAgIQLu2TV80hCgYgZe18ovEhmzANBgkqhkiG9w0BAQsFADBZ
MR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExFzAVBgNVBAsMDmh1eXV1
bWlAcmlyaWthMR4wHAYDVQQDDBVta2NlcnQgaHV5dXVtaUByaXJpa2EwHhcNMTkw
NjAxMDAwMDAwWhcNMzAwNTE5MDM0MjI2WjBCMScwJQYDVQQKEx5ta2NlcnQgZGV2
ZWxvcG1lbnQgY2VydGlmaWNhdGUxFzAVBgNVBAsMDmh1eXV1bWlAcmlyaWthMIIB
IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5fRUIbEv2DjBmK7+syGVvh3I
FWDlVjU9N7ypxauQbXPHAzpATzghLnpm5CqQFoTnJwA4//A85775djcVlsAUqen2
ZYi+4jTYeuRLrAJ0dkrUS8/7+T0fGzGZ8obCsII5iSE2BMS7AxbqlQtClDdkNwcK
rCuzrmIyMA8Bc2V231xIgcWFJ7en8OaZJRlYYK7kp2cJ8g0PbPnVq+9TAfFYcKEy
FWqJsYYY36bLbWyqYXGMOtAh2bhy+YGYL3Jhk+cw7iMCjye4FbDAIQzt9cH1KGGM
2VWZFiwn6VJquX1Z+n9KAhfzxuzYQHSrlJ+Rt++gezpTtNw8q15Ko78oiu7CLQID
AQABo2cwZTAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYD
VR0TAQH/BAIwADAfBgNVHSMEGDAWgBSljCjB0QNrBG+8BV3nFnUyBn54jjAPBgNV
HREECDAGhwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBgQAsUrfA8deCaHYy7wB1jEVK
pNZKRNcDKxqr/PXJQlfwwlq1qZTBzloMNTzfVBRkn/I7y+Bj/b1uYFmjQoQ3qG9s
tIXFCYOop1cLltmWXC479/UtbEmhz0t+mzK0MFkLhxtbKqwvMGbcGGDFI/2/MGZN
XFZXL1bclFieZxO5ePEkZSDkPcWvh9uYWCp8r7H6aAd/iwH4lDxfajyhDneRmd/v
Mq0PgqTZhVHOP7JdVNA+6cewROyPL7ElLs66ujE9hsRvs6eXLjgLZrHOZShnoQxK
JJv8UfoE90FX1uDt9w9i3raig/O3oePNkU263kJlR+J1rdVdYV+pCCb7L4Vk+1l3
S4VFVGVHN8x35dISCJwZrtnqPlfpCiLjtEJOu1zJUEY2Q0n7Km3z3zQcs6iCeOQi
O9MVJ4aiALdNvyCG7lL4+AJ/kWbwHFM6wOAKSrkpZ20msMuEgIlhCOi8PgYlKb+b
V/lV6IJPVrAOOclgcvtfZ/LdsTxn15yLIieqgR0Lf/s=
-----END CERTIFICATE-----

28
security/rustls/key.pem Normal file
View File

@ -0,0 +1,28 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDl9FQhsS/YOMGY
rv6zIZW+HcgVYOVWNT03vKnFq5Btc8cDOkBPOCEuembkKpAWhOcnADj/8Dznvvl2
NxWWwBSp6fZliL7iNNh65EusAnR2StRLz/v5PR8bMZnyhsKwgjmJITYExLsDFuqV
C0KUN2Q3BwqsK7OuYjIwDwFzZXbfXEiBxYUnt6fw5pklGVhgruSnZwnyDQ9s+dWr
71MB8VhwoTIVaomxhhjfpsttbKphcYw60CHZuHL5gZgvcmGT5zDuIwKPJ7gVsMAh
DO31wfUoYYzZVZkWLCfpUmq5fVn6f0oCF/PG7NhAdKuUn5G376B7OlO03DyrXkqj
vyiK7sItAgMBAAECggEBAIabZmAukz4zwwe4cDm1kC0wy73P8Y9sLMCivJKMYkff
vQBjqd91kN7fIbmwPJYiCBlpZPRU0aIqxWZwyj9rgu0Pmn9G884AdzRAzRcMfNX9
6ZXTUsFMCRhnCaHRRsgCAuIFwdQ6wOoHERxb8gZHAm+/vHyaPFz4+D3vmr7NBy+p
fgpdDCGwkltKI73efk6H4oAeyztDwNev/TZ3Y+O3UKuAUfVReBX0us/lYgEf/KXV
USd7envxACy+PDcqmn/HL6IUnbrc1zB92dmSSUUtLjOz//z1zM05ME/E2keMQwsW
7LDen0Lm0Nh6AcOCxmnN4u0lJ3nWzU7PsHJKY/LznPUCgYEA5kQq/AG6LlL9Iu1E
Y55AB1rkvseof41liaqXVccB5tr55IF75d0wPd6jF04W+x6LwmL6EUYPRGkkOdHE
raz9CDE3a7hWbAghxIwLrI1s+faT5aaHG9o6mTeDyfgEEoBg8X2nQHQJPayDJZcW
kiXQyHEtj/G4m/Y+WDFXastZz8MCgYEA/6c8+cI3Slvg3CZLG9f6rdAlrOSIQynF
muXyVeUaxrU0OPC9H3WEwWv7n4adQU2g0L6TBTdlOOiv5SPIsOPQVN2JZVdxwg0V
n5+7/WRrI9rAXnmu1x0q1e/TZ9Msggmrn5SdHaEfuug4DnHv4nct356joDwYB2i3
xYl+yCSMd08CgYEAqduvOaasiG9/e7w6rqGV6dcK1hDCIxVSyXKloAjlRj5SCFXb
53x6kakh9ZcNLMEjp4kLnqJnsLc+mcg7pUHuhZSIpVWdqqN1BV+pXOgWc22JO+bT
05/vigaBmQLzPhKlcH6YWds+1dfkBl6lr7llgfa6/Wv6GlJTOwtqyMSow7ECgYEA
zGQ8j8ICymRihh/ndL9cH5KGTI/5kRjYb1rgQGQG4E8HDW8LBRfDp5BZf9Tz7L3P
kJSMnmMHflQqLJxLW4EHkpH7wxYCUQ589z2R4qhiMCw4GFBYxIsBMEGpVxyyPNTW
baM3afTjlV8LUiEtlHWMK3h9gSIKZAIIytl+jy0JUGkCgYA3wrpcG3wgXeuEtoie
ve/kFS5JRaOeV/9OLE2JGaGaumPlN0L14kCVvb6uqLa/P88BwBUxvGQ7FDBdh4sk
ypuSe9ZPCNDgnsbnfM8QgFqIW6MDdizLtj7no1SKeaUU3JWWc0kH2KWMw/sYZ7ec
0tcEInxEd7FbssGfMqF9fQtnNw==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,51 @@
use std::fs::File;
use std::io::BufReader;
use actix_files::Files;
use actix_web::{middleware, web, App, HttpRequest, HttpResponse, HttpServer};
use rustls::internal::pemfile::{certs, pkcs8_private_keys};
use rustls::{NoClientAuth, ServerConfig};
/// simple handle
async fn index(req: HttpRequest) -> HttpResponse {
println!("{:?}", req);
HttpResponse::Ok()
.content_type("text/plain")
.body("Welcome!")
}
#[actix_web::main]
async fn main() -> std::io::Result<()> {
if std::env::var("RUST_LOG").is_err() {
std::env::set_var("RUST_LOG", "actix_web=info");
}
env_logger::init();
println!("Started http server: 127.0.0.1:8443");
// load ssl keys
let mut config = ServerConfig::new(NoClientAuth::new());
let cert_file = &mut BufReader::new(File::open("cert.pem").unwrap());
let key_file = &mut BufReader::new(File::open("key.pem").unwrap());
let cert_chain = certs(cert_file).unwrap();
let mut keys = pkcs8_private_keys(key_file).unwrap();
config.set_single_cert(cert_chain, keys.remove(0)).unwrap();
HttpServer::new(|| {
App::new()
// enable logger
.wrap(middleware::Logger::default())
// register simple handler, handle all methods
.service(web::resource("/index.html").to(index))
// with path parameters
.service(web::resource("/").route(web::get().to(|| {
HttpResponse::Found()
.header("LOCATION", "/index.html")
.finish()
})))
.service(Files::new("/static", "static"))
})
.bind_rustls("127.0.0.1:8443", config)?
.run()
.await
}

View File

@ -0,0 +1,16 @@
# Actix Web CORS example
## Run Server
```sh
cd web-cors/backend
cargo run
```
## Run Frontend
In a separate terminal, also run:
```sh
cd web-cors/frontend
npm install
npm run serve
```
then open browser at: http://localhost:8080

View File

@ -0,0 +1,14 @@
[package]
name = "actix-web-cors"
version = "1.0.0"
authors = ["krircc <krircc@aliyun.com>"]
edition = "2018"
[dependencies]
actix-web = "3"
actix-cors = "0.5"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
env_logger = "0.8"
futures = "0.3"

View File

@ -0,0 +1,28 @@
use actix_cors::Cors;
use actix_web::{http::header, middleware::Logger, App, HttpServer};
mod user;
#[actix_web::main]
async fn main() -> std::io::Result<()> {
std::env::set_var("RUST_LOG", "actix=info");
env_logger::init();
HttpServer::new(move || {
App::new()
.wrap(
Cors::default()
.allowed_origin("http://localhost:8080")
.allowed_methods(vec!["GET", "POST"])
.allowed_headers(vec![header::AUTHORIZATION, header::ACCEPT])
.allowed_header(header::CONTENT_TYPE)
.supports_credentials()
.max_age(3600),
)
.wrap(Logger::default())
.service(user::info)
})
.bind(("127.0.0.1", 8000))?
.run()
.await
}

View File

@ -0,0 +1,21 @@
use actix_web::{post, web};
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Serialize, Debug)]
pub struct Info {
username: String,
email: String,
password: String,
confirm_password: String,
}
#[post("/user/info")]
pub async fn info(info: web::Json<Info>) -> web::Json<Info> {
println!("=========={:?}=========", info);
web::Json(Info {
username: info.username.clone(),
email: info.email.clone(),
password: info.password.clone(),
confirm_password: info.confirm_password.clone(),
})
}

15
security/web-cors/frontend/.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
.DS_Store
node_modules/
/dist/
.cache
npm-debug.log*
yarn-debug.log*
yarn-error.log*
package-lock.json
# Editor directories and files
.idea
*.suo
*.ntvs*
*.njsproj
*.sln

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>webapp</title>
</head>
<body>
<div id="app"></div>
</body>
</html>

View File

@ -0,0 +1,16 @@
{
"name": "frontend-vue",
"version": "0.1.0",
"description": "webapp",
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"vue": "2.6.12"
},
"devDependencies": {
"@vue/cli-service": "^3.0.0",
"vue-template-compiler": "^2.6.12"
}
}

View File

@ -0,0 +1,149 @@
<template>
<div id="app">
<div id="content">
<div id="title">
<a to="#">SignUp</a>
</div>
<input type="text" name="username" placeholder="Username" v-model="Username" required />
<input type="text" name="email" placeholder="E-mail" v-model="Email" required />
<input type="password" name="password" placeholder="Password" v-model="Password" required/>
<input type="password" name="confirm_password" placeholder="Confirm password" v-model="ConfirmPassword" required/><br/>
<button id="submit" @click="signup">Sign up</button>
<div id="user-info">
<p>Click Above 'Sign up' Button <br> Then Get Your Signup Info!</p>
<p>email : {{ email }}</p>
<p>username {{ username }}</p>
<p>password : {{ password }}</p>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'app',
data () {
return {
Username: '',
Email: '',
Password: '',
ConfirmPassword: '',
email: '',
username: '',
password: ''
}
},
methods: {
signup () {
let username = this.Username
let email = this.Email
let password = this.Password
let confirm_password = this.ConfirmPassword
let data = {
username: username,
email: email,
password: password,
confirm_password: confirm_password
}
fetch('http://localhost:8000/user/info', {
body: JSON.stringify(data),
headers: {
'content-type': 'application/json'
},
method: 'POST',
}).then(response => response.json())
.then(json => {
console.log(json)
this.email = json.email
this.username = json.username
this.password = json.password
})
.catch((e) => {
console.log(e)
})
}
}
}
</script>
<style scoped>
#content {
width: 250px;
margin: 0 auto;
padding-top: 33px;
}
#title {
padding: 0.5rem 0;
font-size: 22px;
font-weight: bold;
background-color:bisque;
text-align: center;
}
input[type="text"],
input[type="password"] {
margin: 6px auto auto;
width: 250px;
height: 36px;
border: none;
border-bottom: 1px solid #AAA;
font-size: 16px;
}
#submit {
margin: 10px 0 20px 0;
width: 250px;
height: 33px;
background-color:bisque;
border: none;
border-radius: 2px;
font-family: 'Roboto', sans-serif;
font-weight: bold;
transition: 0.1s ease;
cursor: pointer;
}
input[type="checkbox"] {
margin-top: 11px;
}
dialog {
top: 50%;
width: 80%;
border: 5px solid rgba(0, 0, 0, 0.3);
}
dialog::backdrop{
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.7);
}
#closeDialog {
display: inline-block;
border-radius: 3px;
border: none;
font-size: 1rem;
padding: 0.4rem 0.8em;
background: #eb9816;
border-bottom: 1px solid #f1b75c;
color: white;
font-weight: bold;
text-align: center;
}
#closeDialog:hover, #closeDialog:focus {
opacity: 0.92;
cursor: pointer;
}
#user-info {
width: 250px;
margin: 0 auto;
padding-top: 44px;
}
@media only screen and (min-width: 600px) {
#content {
margin: 0 auto;
padding-top: 100px;
}
}
</style>

View File

@ -0,0 +1,6 @@
import Vue from 'vue'
import App from './app'
new Vue({
render: h => h(App)
}).$mount('#app')