@TOC[]
一、配置模板全局变量
1.重点
// 1.设置全局变量
res.locals.userinfo = userinfo;
// 2.在任何一个页面中使用
<a>欢迎您 <%=userinfo.username%></a>
2.完整案例
2.1) 在中间件中配置登录者的全局变量
@filename(adminauth.middleware)
import { Injectable, NestMiddleware } from '@nestjs/common';
@Injectable()
export class AdminauthMiddleware implements NestMiddleware {
use(req: any, res: any, next: () => void) {
// console.log('中间件', req.baseUrl);
let pathname = req.baseUrl; // 获取访问的地址
// 1.获取session中保存的用户信息
let userinfo = req.session.userinfo;
// 判断权限(是否登录)
if (userinfo && userinfo.username) {
// 设置全局变量
res.locals.userinfo = userinfo;
console.log('res.locals.userinfo: ', res.locals.userinfo);
next();
} else {
// 未登录时跳转到登录页:排除不需要权限判断的页面(登录、注册、验证码)
if(pathname == '/admin/login' || pathname == '/admin/login/code' || pathname == '/admin/login/doLogin' ) {
next();
}else {
console.log('未登录');
res.redirect('/admin/login') //重定向
}
}
}
}
2.2 在公共头部展示数据
<nav class="navbar navbar-inverse" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<img src="/admin/images/node.jpg" height="44px;" />
</div>
<div class="collapse navbar-collapse" id="example-navbar-collapse">
<ul class="nav navbar-nav navbar-right">
<li><a>欢迎您 <%=userinfo.username%></a>
</li>
<li><a href="/admin/login/loginOut">安全退出</a>
</li>
</ul>
</div>
</div>
</nav>
二、配置可修改的后台地址
2.1 在config.ts中设置全局变量
export class Config{
static adminPath = 'adminxxx'
}
2.1.1 在init.middleware中设置成全局变量
注:在这里配置成全局变量,可以在所有的前端页面中使用。
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Config } from '../config/config'
@Injectable()
export class InitMiddleware implements NestMiddleware {
use(req: any, res: any, next: () => void) {
res.locals.config = Config;
next();
}
}
2.2 在login.controller中使用
重点:@Controller(
${Config.adminPath}/login)
完整代码如下
import { Controller, Get, Render, Request, Response, Post, Body } from '@nestjs/common';
import { ToolsService } from '../../../service/tools/tools.service';
import { AdminService } from '../../../service/admin/admin.service';
import { Config } from '../../../config/config'
@Controller(`${Config.adminPath}/login`)
export class LoginController {
constructor(
private ToolsService: ToolsService,
private adminService: AdminService
) { }
@Get()
@Render('admin/login')
async index() {
return {}
}
// 获取验证码
@Get('code')
getCode(@Request() req, @Response() res) {
let svgCaptcha = this.ToolsService.captcha(); // 服务里面的方法
req.session.code = svgCaptcha.text;
res.type('image/svg+xml'); /*指定返回的类型*/
res.send(svgCaptcha.data); /*给页面返回一张图片*/
}
// 登录
@Post('doLogin')
async doLogin(@Body() body, @Request() req, @Response() res) {
console.log('body: ', body);
console.log('session: ', req.session);
try {
let code: string = body.code;
let username: string = body.username;
let password: string = body.password;
if (username == "" || password.length < 6) {
await this.ToolsService.error(res, '用户名或密码不合法', `/${Config.adminPath}/login`);
} else {
// 注:验证码转化为大写方便比较
if (code.toUpperCase() == req.session.code.toUpperCase()) {
password = this.ToolsService.getMd5(password); // 使用md5加密
// 去数据库查是否有这个用户
let userResult = await this.adminService.find({ 'username': username, 'password': password });
console.log('userResult:', userResult);
if (userResult.length > 0) {
req.session.userinfo = userResult[0];
await this.ToolsService.success(res, `/${Config.adminPath}/main`);
} else {
await this.ToolsService.error(res, '用户名或密码不正确', `/${Config.adminPath}/login`);
}
} else {
await this.ToolsService.error(res, '验证码不正确', `/${Config.adminPath}/login`);
}
}
} catch (error) {
console.log('error', error);
res.redirect(`/${Config.adminPath}/login`);
}
}
@Get('loginOut')
loginOut(@Request() req, @Response() res) {
console.log('退出');
req.session.userinfo = null;
res.redirect(`/${Config.adminPath}/login`);
}
}
注:现在不校验中间件的地方使用
2.3 实验是否成功
浏览器http://localhost:3000/adminxxx/login
,看是否正常显示。
2.4 修改app.module
重点:修改鉴权中间件,让’admin/*'下的路由都经过中间件
.apply(AdminauthMiddleware)
.forRoutes(`${Config.adminPath}/*`)
完整例子
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { AdminModule } from './module/admin/admin.module';
import { DefaultModule } from './module/default/default.module';
import { ApiModule } from './module/api/api.module';
import { MongooseModule } from '@nestjs/mongoose';
import { AdminauthMiddleware } from './middleware/adminauth.middleware';
import { InitMiddleware } from './middleware/init.middleware';
import { Config } from './config/config';
@Module({
imports: [AdminModule, DefaultModule, ApiModule,
// mongoose连接数据库
MongooseModule.forRoot("mongodb://127.0.0.1:27017/nestxiaomi")
],
controllers: [],
providers: [],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
// 访问admin下的东西时才用鉴权中间件
.apply(AdminauthMiddleware)
.forRoutes(`${Config.adminPath}/*`)
.apply(InitMiddleware)
.forRoutes('*')
}
}
2.5 修改中间件
@filename(adminauth.middleware)
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Config } from '../config/config';
@Injectable()
export class AdminauthMiddleware implements NestMiddleware {
use(req: any, res: any, next: () => void) {
// console.log('中间件', req.baseUrl);
let pathname = req.baseUrl; // 获取访问的地址
// 1.获取session中保存的用户信息
let userinfo:any = req.session.userinfo; // req.session.userinfo
// 判断权限(是否登录)
if (userinfo && userinfo.username) {
// 设置全局变量
res.locals.userinfo = userinfo;
next();
} else {
// 未登录时跳转到登录页:排除不需要权限判断的页面(登录、注册、验证码)
if(pathname == `/${Config.adminPath}/login` || pathname == `/${Config.adminPath}/login/code` || pathname == `/${Config.adminPath}/login/doLogin`) {
next();
}else {
console.log('未登录');
res.redirect(`/${Config.adminPath}/login`) //重定向
}
}
}
}
2.6 修改前端页面中用到的路由
1. login.ejs
重点:验证码处用到路由
1.验证码:
<img id="verify_img" src="/<%=config.adminPath%>/login/code" title="看不清?点击刷新"
onclick="javascript:this.src='/<%=config.adminPath%>/login/code?mt='+Math.random()">
2.登录
<form action="/<%=config.adminPath%>/login/doLogin" method="post" id="myform">
完整例子:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>用户登录</title>
<!-- 注css 文件饮用前加'/' -->
<link rel="stylesheet" href="/admin/css/login.css">
</head>
<body>
<div class="container">
<div id="login">
<form action="/<%=config.adminPath%>/login/doLogin" method="post" id="myform">
<div class="l_title">通用商城后台管理系统</div>
<dl>
<dd>管理员姓名:<input class="text" type="text" name="username" id="username"></dd>
<dd>管理员密码:<input class="text" type="password" name="password" id="password"></dd>
<dd>验 证 码:<input id="verify" type="text" name="code">
<img id="verify_img" src="/<%=config.adminPath%>/login/code" title="看不清?点击刷新"
onclick="javascript:this.src='/<%=config.adminPath%>/login/code?mt='+Math.random()">
</dd>
<dd><input type="submit" class="submit" name="dosubmit" value=""></dd>
</dl>
</form>
</div>
</div>
</body>
</html>
2.7 其他
1.controller中使用方法
// 1.引入config
import { Config } from '../../../config/config'
// 2.修改路由
@Controller(`${Config.adminPath}/login`)
// 3.用到路由处用config.adminPath替换admin
this.ToolsService.error(res, '用户名或密码不合法', `/${Config.adminPath}/login`);
2.前端模板中的使用
重点:<a href="/<%=config.adminPath%>/login/loginOut">安全退出</a>
完整例子:
<nav class="navbar navbar-inverse" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<img sr c="/admin/images/node.jpg" height="44px;" />
</div>
<div class="collapse navbar-collapse" id="example-navbar-collapse">
<ul class="nav navbar-nav navbar-right">
<li><a>欢迎您 <%=userinfo.username%></a></li>
<li><a href="/<%=config.adminPath%>/login/loginOut">安全退出</a>
</li>
</ul>
</div>
</div>
</nav>
三、nestjs扩展模板方法
重点:新建一个类 – 在中间件中处理成全局方法 – 在模板中使用。
需求:在前端模板中处理字符串。
新建helper.ts
export class Helper{
static title = "我是全局的title";
static substring(str:string, start:number, end:number) {
if(end) {
return str.substring(start, end);
}else {
return str.substring(start);
}
}
}
配置成全局方法
@filename(init.middleware)
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Config } from '../config/config';
import { Helper } from '../extend/helper';
@Injectable()
export class InitMiddleware implements NestMiddleware {
use(req: any, res: any, next: () => void) {
res.locals.config = Config;
res.locals.helper = Helper;
next();
}
}
前端页面中使用
@filename(welcome.ejs)
截取:<%=helper.substring(userinfo.username, 3)%>