2019-5-10lesson

May 10, 2019

passport实现oauth2登录【个人中心】流程

  1. 首先服务器增加入口路由 /auth/${project} 权限为public。这样前段可通过curl -X GET host/auth/${project} 进入到此方法.

配置route:

1
2
3
4
5
{
path: '/auth/${project}',
method: 'GET',
middleware: [passport.authenticate('${project}')]
}
  1. App.ts 设置passport
1
2
3
4
5
6
7
8
9
app.use(cookieParser())
app.use(session({
... // set up session
}))
app.use(passport.initialize())
app.use(passport.session())
passport.use(Auth.${project}Strategy) // 划重点
passport.serializeUser(Auth.serializeUser)
passport.deserializeUser(Auth.deserializeUser)
  1. 前往Auth 增加${project}Strategy 配置和回调
1
2
3
4
5
6
export default class AuthClass {
public static ${project}Strategy = new AAStrategy(StrategyOptionsRequest, async (req:Request, accessToken:string, refreshToken:string, profile:any, done:Function) => {
req.session.userProfile = profile._json || {}
done(null, false)
})
}

AAStrategy 是要重新配置的class,稍后说明;StrategyOptionsRequest 为需要输入的options。配置请查看Oauth2Strategy.StrategyOptionsWithRequest。

  1. AAStrategy 制作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
export default class AAStrategy extends Oauth2Strategy {
private _userProfileURL:string
constructor (options:IStrategyOptions, verify:Oauth2Strategy.VerifyFunctionWithRequest) { // IStrategyOptions extends Oauth2Strategy.StrategyOptionsWithRequest
super(options, verify)
this.name = '${project}'
this._oauth2.useAuthorizationHeaderforGET(true)

let urlParams = `${checkAspect_id}=${encodeURIComponent(options.clientID)}&` // checkAspect 为您目标工程的要求;不要忘记最后一个**&**
this._userProfileURL = `${config.authUrl}/api/user/?${urlParams}client_secret=${encodeURIComponent(options.clientSecret)}&` // 不要忘记**&**
}
public userProfile (accessToken:string, done:any) {
this._userProfileURL = this._userProfileURL + (`access_token=${encodeURIComponent(accessToken)}`)
this._oauth2.get(this._userProfileURL, accessToken, function (err:any, body:any, res:any) {
if (err) {
return done(new InternalOAuthError('Failed to fetch user profile', err))
}
done(null, {
_raw: body,
_json: json
})
})
}
}
  1. 路由重定向回本地认证登录

由于我们在填写IStrategyOptions 时,options.callbackURL 填写为${config.authCbURL}/auth/${project}/callback

那么我们在路由增加:

1
2
3
4
5
6
7
8
9
10
11
12
{
path: '/auth/${project}/callback',
method: 'GET',
middleware: [passport.authenticate('${project}', {
failureRedirect: '/auth/login' // 划重点,重定向回来之后会调用/auth/login
})]
},
{
path: '/auth/login',
method: 'GET',
middleware: [Auth.authLogin]
}
1
2
3
4
5
6
7
8
9
10
11
12
public static authLogin (req:Request, res:Response) {
if (!(req.session.userProfile && req.session.userProfile.email)) return res.redirect('/login')

req.session.userProfile = null

...
do something like
1. UserModel.findOrCreate(userProfile) defer err, user
2. req.login(user)

return res.redirect('/user/home')
}
1
2
3
4
5
6
7
{
path: '/profile',
method: 'GET',
middleware: [(req:Request, res:Response) => {
res.status(200).send(req.user)
}]
}

以上服务端方面全部完成。

流程也是比较直观的。

最后的routeRoute 是为了给前端作为判断成功与否的作用。

1 << 1, 1 << 2 权限位偏移

使用机器计算2进制偏移位来比对用户的权限位。

比如:

1
2
3
1 << 1 === admin,
1 << 30 === public,
1 << 31 === anon

结果是,权限卡槽最好至多放32个(计算机可能是为32bit)

判断时,只需在对应权限位进行与或对比即可

微信web登录,内测配置

公司在审核通过后,微信后台配置域名:ip.gogal.ml:5700这样便可做到本地开发。注意:5700

同时服务器callbackURL:http://ip.gogal.ml:5700/auth/weixin/callback 这样即可完美跳转callback。

记录下2019-4-26晚上学科目三犯的错

1 换挡

上5挡时,出现挂错3档位

2 抖动

换挡时,出现抖动。要先上档位速度,然后踩离合挂到对应档位,送离合,稳住油门。

3 进入待转区、转弯

1
2
3
4
5
转弯、掉头时,到前方一定距离,稳定车速在20多一点点,打转向灯,一定要稳住方向盘3s不动.

然后在实线前左转进入待转区。速度稳住.在一定距离时,踩离合踩刹车,车头快盖住线时停下。

1挡出发(转弯上2挡), 有“打半圈”、“打一圈少一点”、“一圈半少一点”

4 靠边停车

靠边停车,在听到声音后,“开右转向灯3s”、“方向稳住不动”、“减速到1挡”、“然后方向盘向右稍微倾斜”、“车子线方向靠”。

车头感觉车身和线重合,后视镜位置看着差不多,否则停下之后还可微调。

“确认停好后”,回空挡拉手刹。这时会提示挺好出发。

“打左转向灯3s”、“打左半圈”、“上2挡”、“上3挡”

在路上想到一个问题

在路上,我骑车时闯一个红灯10s,到下个路口时,刚好红灯10s。

如果我等,那刚刚闯红灯是赚了还是赔了。

如果我直接闯,那我是赚了多少时间?

上线vue

yarn build

npm install -g serve

serve -s ./dist //本地先查看是否OK

将dist 文件目录放到服务器。之后nginx 指向该目录地址

再讲一遍vue build 上线的全过程

检查当前环境

确认好 /src/service/http 设置axios 的default.baseURL

由于本人服务器及后台代码配置为 https://gogal.ml/stratege/。路由为 /api/xxx

那么axios的基本路由配置为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
if (process.env.NODE_ENV === 'development') {
axios.defaults.baseURL = '/api'
} else {
axios.defaults.baseURL = '/stratege'
}

如果是本地测试环境,那么你需要到/config/index.js 里面修改dev/proxyTable:

dev: {
...
proxyTable: {
'/api': {
target: 'http://localhost:${your port}' // 或者https://gogal.ml/stratege
secure: true,
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}

这样服务器才能找到同个域名下的api.

确认好webpack 配置的uglifyjs 是开启的

/config/index.js 里面出现的 *sourceMap 都改为false

这样线上代码就不会裸奔啦。

开始build

yarn build

完成之后,先本地测试一遍:

npm install -g serve

serve -s ./dist

然后点一点,玩一玩。

这时确认ok后,将dist 目录下的favicon.ico index.html static 目录 放到服务器 /var/www/目录下。【Filezilla】

配置nginx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
...
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request"'
'$status $body_types_sent "$http_referer"'
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
keepalive_timeout 65;

server {
listen 443 default ssl;
server_name www.gogal.ml gogal.ml;

ssl on;
ssl_certificate ???
ssl_certificate_key ???
# managerd by Certbot

root /var/www;
index index.html index.htm;

location / {
root /var/www;
index index.html index.htm;
try_files $uri $uri/ /index.html; # 作用是vue刷新 不会出现404 等情况
}

location @fallback {
rewrite ^.*$ /index.html break;
}

location /stratege/ {
proxy_pass http://127.0.0.1:${your server port}/;
}
}
}
vim /etc/nginx/nginx.conf
service nginx restart

以上便能成功啦。

曾经我问过一个成功人士(我),你为什么如此成功?

成功人士(我)回答我说,当你是商人时,你便做商人的事。如果你不知道你要卖什么,那你就应该去做技术,然后将技术当成你的商品,从小做起。你没得选择。

不怕劳苦。当身边的人一再厌恶你的穷病时,一定要坚持住自己的理想。

是的,穷病,比抽烟吸毒杀人,还要可怕。而你空怀一身绝技没法及时变现。

你要的很多,你的身体却制约你。时常感到时间不够用,加班加点,但是一觉睡下去却远远不够。

成功人士,便是熬过最穷苦,依然坚持自己的愿景,含着泪坚持下去的人。

极度的黑暗,就是天明之时。

曾经的你,未来的我?现在的我?

希望未来能放下手中工作消遣时,回头看看这时的感叹。2019-4-30 aker

mongodb 出现error - [test] UncaughtException: E11000 duplicate key error collection: authServer.users index

原因是设置unique 字段时,在多个doc 里面仍然有出现null 数据。

网络很多人都是建议删除数据库重来、删除索引等等。都没能解决此问题。

这时,使用sparse 稀疏索引 以解决此问题。

Vue axios POST 请求时 会使用OPTIONS 同时解决跨域问题

OPTIONS 的解决方案:

1
2
3
4
5
6
7
8
9
10
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8'

axios.interceptors.request.use(
config => {
if (config.method === 'post') {
config.data = qs.stringify(config.data)
}
return config
}
}

使用qs 同时在header 里面申明使用的格式

跨域使用Chrome 浏览器插件Moesif CORS 即可解决

!!!!注意

开发时注意,本机为黑苹果,遇到一个特别的情况:

昨天还能正常使用,开发dev,突然怎么改vueProject/config/index.js - proxyTable 都没用。

最后解决方法:使用一个新的域名代替localhost,重设置到/etc/hosts.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
1:sudo vim /etc/hosts && 新增 127.0.0.1  test.company.com
2:修改proxyTable: {
'/api': {
target: 'http://test.company.com:${your port}',
secure: false,
changeOrigin: false,
pathRewrite: {
'/api': '/'
}
}
}

3: 修改vueProject/config/index.js - dev: {
host: 'test.company.com'
}

原因:

估计是本地DNS 有缓存。一直提示如下

[HPM] Error occurred while trying to proxy

或者

axios 请求成了:POST http://localhost:${frontend port}/api/method, 服务器始终报错(本人处报:EBADCSRFTOKEN)

最终修改完成。好开心啊。

En:

I meet [HPM] Error occurred while trying to proxy request just today.finally solve it.

Scene:

Yesterday, VueProject worked well. Git checkout back to some week ago, still didn’t work( Used to be working well ).

Until this step save me:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
1: sudo vim /etc/hosts && 127.0.0.1   test.company.com # any host is available
2: edit VueProject / config / index.js - proxyTable: {
'/api': {
target: 'http://text.company.com:${your server port}',
secure: false,
changeOrigin: false,
pathRewrite: {
'/api': '/'
}
}
}
3: edit VueProject / config / index.js - dev: {
host: 'test.company.com'
}

上线express + vue 两种方案

express vue 分开发布

Nginx location / { root: 放Vue 路径 }
Nginx location / app { proxy 端口 }

此时只要Vue 的axios.defaults.baseURL = ‘/app’

以上分离很好使。但是同时维护两个,做法不太正规。

express vue 使用res.sendFile Nginx 反向代理端口即可

下面都是重点:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
docker 目录:
/dist
/app.js
/routes/
/index.js 路由
/public/
/index.html
/static/

1: Vue 前段yarn build 之后,基本不需要其他操作

// 下面这句话res.sendFile 时,发送static 文件,找寻的目录.
// 否则pc 报`Uncaught SyntaxError: Unexpected token <`
2: backend/app.ts - app.use(express.static(path.join(__dirname, 'public/')))

// 下面这句话重点: public 不要写错,不要写错,不要写错
// root 不是route,不是route,不是route
3: backend/routes/index.ts - res.sendFile("index.html", { root: path.join(__dirname, '../public')})

__dirname your current excuse file path

process.cwd() your project root path

以上终于解决!!!

昨天VPS 里面的数据库Mongodb 早上还有数据,下午突然没有了

很疑惑,如果不知道原因,之后再出现就会有大问题。于是看了看里面的表。

知道傍晚,发现里面有张表很奇怪:叫做hacked_by_unistellar

我似乎没有搞过这个表啊。

进去一看:db.restore.find() 显示我之前的表被脱裤,要钱,联系unistellar@hotmail.com 邮箱。

幸好数据不多。知道什么原因,那就好搞了。

首先,数据库没设置密码,那为什么会暴露在公网。

我启动mongo 语句是docker run --name mongo -p 27017:27017 mongo

如果是直接使用mongod 那么启动时默认分配的是127.0.0.1:27017

如果是docker 启动的话,不指定ip,docker 会直接暴露在公网,任何人直接ip + 27017 或者mysql 的3306 直接就脱裤了。

正确语句是:docker run --name mongo -p 127.0.0.1:27017:27017 mongo

db.createUser({ user: ‘akerdi’, pwd: ‘my-fucking_password’, roles: [ { role: ‘userAdminAnyDatabase’, db: ‘admin’ } ]});

正确思考Mongo 是什么。

数据库实质上是一个管理物理数据的软件,充当管理介质。

那么上面很重要的点是,mongo 需要配置文件。

docker run -p 27017:27017 -v /mongo_configdb:/data/configdb -v /mongo_db:/data/db -d mongo # 这里重点是将配置文件映射到相应的目录。之后所有映射过来的都会使用相同配置

docker ps # 找到对应containerId

docker exec -it containerId mongo admin # 进入mongodb 或者 docker exec -it containerId bash 之后 mongo

> use cool_db #mongo 内部环境,使用cool_db 为例

> db.createUser({ user: 'aker', pwd: 'your password', roles: [{ role: 'readWrite', db: 'cool_db'}] });

> exit

$ docker stop containerId && docker rm containerId # 之后使用 --auth 之前的mongo 软件介质不需要了

# 这时使用之前映射的目录,便是相同的配置,同时mongo 还带有验证
# 127.0.0.1:27017 可以使ip 映射局限本机,否则为0.0.0.0:27017
# --rm 使mongo 在stop 时自动删除
doceker run --name mongo -d -p 127.0.0.1:27017:27017 -v /mongo_configdb:/data/configdb -v /mongo_db:/data/db -d --rm mongo --auth

参考自:

  1. https://www.jianshu.com/p/2181b2e27021
  2. https://stackoverflow.com/questions/34559557/how-to-enable-authentication-on-mongodb-through-docker