

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
12345# 权限管理(Authority)67cool-admin 采用是是一种无状态的权限校验方式。[jwt](mdc:https:/jwt.io/introduction), 通俗地讲他就是把用户的一些信息经过处理生成一段加密的字符串,后端解密到信息进行校验。而且这个信息是带有时效的。89cool-admin 默认约定每个模块下的 `controller/admin`为后台编写接口,`controller/app`编写对外如 app、小程序的接口。1011- 框架会对路由前缀 `/admin/**` 开头的接口进行权限校验,校验逻辑写在`base`模块下的`middleware/authority.ts`中间件12- 框架会对路由前缀 `/app/**` 开头的接口进行权限校验,校验逻辑写在`user`模块下的`middleware/app.ts`中间件1314::: tip15也就是说模块`controller/admin`与`controller/app`是需要进行 token 校验的,如果你不想 token 校验有两种方式:1617- 使用路由标签的形式,忽略 token 校验,详细查看[路由标签](mdc:src/guide/core/controller.html#路由标签);1819- 新建其他的文件夹比如:`controller/open`;2021这样就不会提示登录失效~22:::2324## 登录2526查询校验用户信息,然后将用户信息用 jwt 的方式加密保存返回给客户端。2728`src/app/modules/base/service/sys/login.ts`2930```ts31/**32 * 登录33 * @param login34 */35 async login(login: LoginDTO) {36 const { username, captchaId, verifyCode, password } = login;37 // 校验验证码38 const checkV = await this.captchaCheck(captchaId, verifyCode);39 if (checkV) {40 const user = await this.baseSysUserEntity.findOne({ username });41 // 校验用户42 if (user) {43 // 校验用户状态及密码44 if (user.status === 0 || user.password !== md5(password)) {45 throw new CoolCommException('账户或密码不正确~');46 }47 } else {48 throw new CoolCommException('账户或密码不正确~');49 }50 // 校验角色51 const roleIds = await this.baseSysRoleService.getByUser(user.id);52 if (_.isEmpty(roleIds)) {53 throw new CoolCommException('该用户未设置任何角色,无法登录~');54 }5556 // 生成token57 const { expire, refreshExpire } = this.coolConfig.jwt.token;58 const result = {59 expire,60 token: await this.generateToken(user, roleIds, expire),61 refreshExpire,62 refreshToken: await this.generateToken(63 user,64 roleIds,65 refreshExpire,66 true67 ),68 };6970 // 将用户相关信息保存到缓存71 const perms = await this.baseSysMenuService.getPerms(roleIds);72 const departments = await this.baseSysDepartmentService.getByRoleIds(73 roleIds,74 user.username === 'admin'75 );76 await this.coolCache.set(77 `admin:department:${user.id}`,78 JSON.stringify(departments)79 );80 await this.coolCache.set(`admin:perms:${user.id}`, JSON.stringify(perms));81 await this.coolCache.set(`admin:token:${user.id}`, result.token);82 await this.coolCache.set(`admin:token:refresh:${user.id}`, result.token);8384 return result;85 } else {86 throw new CoolCommException('验证码不正确');87 }88 }89```9091## 权限配置9293admin 用户拥有所有的权限,无需配置,但是对于其他只拥有部分权限的用户,我们得选择他们的权限,在这之前我们得先录入我们的系统有哪些权限是可以配置的9495可以登录后台管理系统,`系统管理/权限管理/菜单列表`96979899## 选择权限100101新建一个角色,就可以为这个角色配置对应的权限,用户管理可以选择对应的角色,那么该用户就有对应的权限,一个用户可以选择多个角色102103104105## 全局校验106107通过一个全局的中间件,我们在全局统一处理,这样就无需在每个 controller 处理,显得有点多余。108109`src/app/modules/base/middleware/authority.ts`110111```ts112import { App, Config, Middleware } from "@midwayjs/core";113import * as _ from "lodash";114import { RESCODE } from "@cool-midway/core";115import * as jwt from "jsonwebtoken";116import { NextFunction, Context } from "@midwayjs/koa";117import { IMiddleware, IMidwayApplication } from "@midwayjs/core";118119/**120 * 权限校验121 */122@Middleware()123export class BaseAuthorityMiddleware124 implements IMiddleware<Context, NextFunction>125{126 @Config("koa.globalPrefix")127 prefix;128129 @Config("module.base")130 jwtConfig;131132 coolCache;133134 @App()135 app: IMidwayApplication;136137 resolve() {138 return async (ctx: Context, next: NextFunction) => {139 let statusCode = 200;140 let { url } = ctx;141 url = url.replace(this.prefix, "");142 const token = ctx.get("Authorization");143 const adminUrl = "/admin/";144 // 路由地址为 admin前缀的 需要权限校验145 if (_.startsWith(url, adminUrl)) {146 try {147 ctx.admin = jwt.verify(token, this.jwtConfig.jwt.secret);148 } catch (err) {}149 // 不需要登录 无需权限校验150 if (new RegExp(`^${adminUrl}?.*/open/`).test(url)) {151 await next();152 return;153 }154 if (ctx.admin) {155 // 超管拥有所有权限156 if (ctx.admin.username == "admin" && !ctx.admin.isRefresh) {157 await next();158 return;159 }160 // 要登录每个人都有权限的接口161 if (new RegExp(`^${adminUrl}?.*/comm/`).test(url)) {162 await next();163 return;164 }165 // 如果传的token是refreshToken则校验失败166 if (ctx.admin.isRefresh) {167 ctx.status = 401;168 ctx.body = {169 code: RESCODE.COMMFAIL,170 message: "登录失效~",171 };172 return;173 }174 // 需要动态获得缓存175 this.coolCache = await ctx.requestContext.getAsync("cool:cache");176 // 判断密码版本是否正确177 const passwordV = await this.coolCache.get(178 `admin:passwordVersion:${ctx.admin.userId}`179 );180 if (passwordV != ctx.admin.passwordVersion) {181 ctx.status = 401;182 ctx.body = {183 code: RESCODE.COMMFAIL,184 message: "登录失效~",185 };186 return;187 }188 const rToken = await this.coolCache.get(189 `admin:token:${ctx.admin.userId}`190 );191 if (!rToken) {192 ctx.status = 401;193 ctx.body = {194 code: RESCODE.COMMFAIL,195 message: "登录失效或无权限访问~",196 };197 return;198 }199 if (rToken !== token && this.jwtConfig.sso) {200 statusCode = 401;201 } else {202 let perms = await this.coolCache.get(203 `admin:perms:${ctx.admin.userId}`204 );205 if (!_.isEmpty(perms)) {206 perms = JSON.parse(perms).map((e) => {207 return e.replace(/:/g, "/");208 });209 if (!perms.includes(url.split("?")[0].replace("/admin/", ""))) {210 statusCode = 403;211 }212 } else {213 statusCode = 403;214 }215 }216 } else {217 statusCode = 401;218 }219 if (statusCode > 200) {220 ctx.status = statusCode;221 ctx.body = {222 code: RESCODE.COMMFAIL,223 message: "登录失效或无权限访问~",224 };225 return;226 }227 }228 await next();229 };230 }231}232```233234## 令牌续期235236jwt 加密完的字符串是有时效的,系统默认时效时间为 2 个小时。这期间就需要续期令牌才可以继续操作。237238框架登录设置了一个 refreshToken,默认过期时间为 30 天。可以使用这个去换取新的 token,这时候又可以延长 2 个小时。239240## 其他权限241242你可以单独编写一个中间间来控制其他权限,如 app、小程序及其他对外接口,但是可以参考后台管理系统权限过滤、token 生成校验的实现方式243
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| cool-team-official/cool-admin-midway.cursor/rules/cache.mdc · 3.3k | Cursor rules | no sections | 58/100 | today | |
| cool-team-official/cool-admin-midway.cursor/rules/controller.mdc · 3.3k | Cursor rules | api | 46/100 | today | |
| cool-team-official/cool-admin-midway.cursor/rules/db.mdc · 3.3k | Cursor rules | setupdatabase | 62/100 | today | |
| cool-team-official/cool-admin-midway.cursor/rules/event.mdc · 3.3k | Cursor rules | no sections | 45/100 | today | |
| cool-team-official/cool-admin-midway.cursor/rules/module.mdc · 3.3k | Cursor rules | no sections | 50/100 | today | |
| cool-team-official/cool-admin-midway.cursor/rules/service.mdc · 3.3k | Cursor rules | database | 54/100 | today | |
| cool-team-official/cool-admin-midway.cursor/rules/socket.mdc · 3.3k | Cursor rules | no sections | 58/100 | today | |
| cool-team-official/cool-admin-midway.cursor/rules/task.mdc · 3.3k | Cursor rules | style | 58/100 | today | |
| cool-team-official/cool-admin-midway.cursor/rules/tenant.mdc · 3.3k | Cursor rules | no sections | 50/100 | today | |
| cool-team-official/cool-admin-midway.cursorrules · 3.3k | .cursorrules | no sections | 39/100 | today |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126 | Cursor rules | setupbuildtestlint-format+6 | 100/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 46 | Cursor rules | testlint-formatstylearch+5 | 100/100 | 14 days ago | |
| Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| markstev/mark-starter.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+6 | 99/100 | 14 days ago | |
| dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| langflow-ai/langflow.cursor/rules/docs_development.mdc · 153k | Cursor rules | setupbuildtestlint-format+7 | 97/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 46 | Cursor rules | teststyletesting-strategysecurity+3 | 97/100 | 14 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/cool-team-official-cool-admin-midway-cursor-rules-authority)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.