Coder Social home page Coder Social logo

pleaseyang / ity Goto Github PK

View Code? Open in Web Editor NEW
48.0 48.0 18.0 2.68 MB

基于laravel + vue的基础后台,前后端分离,欢迎fork&start,不合理的地方也欢迎批评指正

License: MIT License

PHP 99.10% Batchfile 0.03% HTML 0.87%
ity jwt laravel rbac vue

ity's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

ity's Issues

微信支付v3平台证书会在过期前5天会存在两个,建议支持多证书

see https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/wechatpay5_0.shtml

由于旧证书过期前的5天内,微信支付会同时使用新旧证书,因此为实现新老证书的平滑切换,商户系统需支持多平台证书。

// 根据通知的平台证书序列号,查询本地平台证书文件,
$platformPublicKeyInstance = Rsa::from('file://' . $wechatPayConfig->where('key', 'wechat_pay_cert')->value('value'), Rsa::KEY_TYPE_PUBLIC);
// 检查通知时间偏移量,允许5分钟之内的偏移

建议上述程序逻辑设计,支持多证书加载。

jwt过期后,系统捕获到的异常存在问题,导致无法做无痛刷新token

bug反馈:当把jwt的ttl设置为1分钟后,无痛刷新token存在bug,希望作者核实一下。

操作过程:

1.设置jwt的ttl为1分钟。

2.创建刷新token的middleware,以下是刷新token的中间件代码:

checkForToken($request); //如果格式通过,验证是否是专属于这个的token //获取当前守护的名称 $current_guard = Auth::getDefaultDriver(); //获取当前token $token = Auth::getToken(); //即使过期了,也能获取到token里的载荷信息。 $payload = Auth::manager()->getJWTProvider()->decode($token->get()); //如果不包含guard字段或者guard所对应的值与当前的guard守护值不相同,证明是不属于当前guard守护的token if(empty($payload['guard']) || $payload['guard'] != $current_guard){ throw new TokenInvalidException(); } try{ //检测用户的登录状态,如果正常则通过 if($this->auth->parseToken()->authenticate()){ return $next($request); } throw new UnauthorizedHttpException('jwt-auth','未登录'); }catch(TokenExpiredException $exception){ try{ //刷新用户的token $token = $this->auth->refresh(); //使用一次性登录以保证此次请求的成功 Auth::onceUsingId($this->auth->manager()->getPayloadFactory()->buildClaimsCollection()->toPlainArray()['sub']); //将token存入数据库 $user = Auth::user(); SaveLastTokenJob::dispatch($user,$token); }catch(JWTException $exception) { //如果捕获到此异常,即代表refresh_token也过期了,用户无法刷新令牌,需要重新登录。 throw new UnauthorizedHttpException('jwt-auth', $exception->getMessage()); } } //在响应头中返回新的token return $this->setAuthenticationHeader($next($request), $token); } } 存在的bug: 当token过期后,这行代码$this->auth->parseToken()->authenticate()始终抛出的是UnauthorizedHttpException的exception,导致该中间件无法捕获TokenExpiredException 期望结果: token过期,应该抛出的是TokenExpiredException

建议`chain`用法以标准的`uri_template`方式传参

->chain('v3/pay/transactions/id/' . $transactionId)
->get(['query' => ['mchid' => $merchantId]]);

当然这里的拼接方式是可以工作的,不过仍然建议用标准用法来构造请求,形如:

->chain('v3/pay/transactions/id/{transaction_id}')
->get(['query' => ['mchid' => $merchantId], 'transaction_id' => $transactionId])

另外建议增加依赖 iwechatpay/openapi dev包,上述代码即可以在JB IDE上书写成

->v3->pay->transactions->id->_transaction_id_
->get(['query' => ['mchid' => $merchantId], 'transaction_id' => $transactionId])

即带请求数据结构基础语法提示。

me 接口问题

我运行你的项目,发现me的返回数据,和你示例网站上的不一样。多了一个item。而且permissions 没有值。
{"success":true,"code":200,"locale":"zh-CN","message":"请求成功","data":{"item":{"id":1,"name":"admin","status":1,"email":"[email protected]","email_verified_at":null,"created_at":"2020-12-25 16:13:06","updated_at":"2020-12-25 16:13:06","accessedRoutes":[{"id":1,"pid":0,"path":"/system","component":"layout/Layout","name":"system","meta":{"title":"system","icon":"el-icon-s-tools","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":false,"redirect":"noRedirect","children":[{"id":2,"pid":1,"path":"/permission-role","component":"rview","name":"permission-role","meta":{"title":"permission-role","icon":"lock","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":false,"redirect":"noRedirect","children":[{"id":3,"pid":2,"path":"permissions","component":"permission/permissions","name":"permission.permissions","meta":{"title":"permission.permissions","icon":"el-icon-key","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":false,"children":[{"id":4,"pid":3,"path":"permission/create","component":"permission/create","name":"permission.create","meta":{"title":"permission.create","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":5,"pid":3,"path":"permission/update","component":"permission/update","name":"permission.update","meta":{"title":"permission.update","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":6,"pid":3,"path":"permission/delete","component":"permission/delete","name":"permission.delete","meta":{"title":"permission.delete","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":7,"pid":3,"path":"permission","component":"permission/permission","name":"permission.permission","meta":{"title":"permission.permission","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]}]},{"id":8,"pid":2,"path":"roles","component":"role/roles","name":"role.roles","meta":{"title":"role.roles","icon":"el-icon-s-custom","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":false,"children":[{"id":9,"pid":8,"path":"role/create","component":"role/create","name":"role.create","meta":{"title":"role.create","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":10,"pid":8,"path":"role/update","component":"role/update","name":"role.update","meta":{"title":"role.update","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":11,"pid":8,"path":"role/delete","component":"role/delete","name":"role.delete","meta":{"title":"role.delete","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":12,"pid":8,"path":"role/role","component":"role/role","name":"role.role","meta":{"title":"role.role","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":13,"pid":8,"path":"role/syncPermissions","component":"role/syncPermissions","name":"role.syncPermissions","meta":{"title":"role.syncPermissions","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":14,"pid":8,"path":"role/syncRoles","component":"role/syncRoles","name":"role.syncRoles","meta":{"title":"role.syncRoles","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]}]}]},{"id":21,"pid":1,"path":"/activeLogs","component":"activeLog/activeLogs","name":"activeLog.activeLogs","meta":{"title":"activeLog.activeLogs","icon":"el-icon-tickets","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":false,"children":[]},{"id":22,"pid":1,"path":"/nginxLogs","component":"nginx/logs","name":"nginx.logs","meta":{"title":"nginx.logs","icon":"el-icon-tickets","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":false,"children":[]},{"id":23,"pid":1,"path":"/exceptionErrors","component":"exceptionError/exceptionErrors","name":"exceptionError.exceptionErrors","meta":{"title":"exceptionError.exceptionErrors","icon":"el-icon-warning","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":false,"children":[{"id":24,"pid":23,"path":"exceptionErrors/amended","component":"exceptionError/amended","name":"exceptionError.amended","meta":{"title":"exceptionError.amended","icon":"el-icon-warning","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]}]},{"id":25,"pid":1,"path":"/exceptionErrors/logFiles","component":"exceptionError/logFiles","name":"exceptionError.logFiles","meta":{"title":"exceptionError.logFiles","icon":"el-icon-tickets","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":false,"children":[]},{"id":31,"pid":1,"path":"/files","component":"file/files","name":"file.files","meta":{"title":"file.files","icon":"el-icon-folder","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":false,"children":[{"id":32,"pid":31,"path":"file/makeDirectory","component":"file/makeDirectory","name":"file.makeDirectory","meta":{"title":"file.makeDirectory","icon":"el-icon-folder-add","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":33,"pid":31,"path":"file/deleteDirectory","component":"file/deleteDirectory","name":"file.deleteDirectory","meta":{"title":"file.deleteDirectory","icon":"el-icon-folder-delete","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":34,"pid":31,"path":"file/upload","component":"file/upload","name":"file.upload","meta":{"title":"file.upload","icon":"el-icon-upload","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":35,"pid":31,"path":"file/download","component":"file/download","name":"file.download","meta":{"title":"file.download","icon":"el-icon-download","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":36,"pid":31,"path":"file/delete","component":"file/delete","name":"file.delete","meta":{"title":"file.delete","icon":"el-icon-delete","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]}]}]},{"id":15,"pid":0,"path":"/admins","component":"layout/Layout","meta":{"title":"admin.admins","icon":"el-icon-user-solid","roles":[1],"noCache":true,"breadcrumb":false,"affix":false},"hidden":false,"children":[{"id":16,"pid":15,"path":"admin/create","component":"admin/create","name":"admin.create","meta":{"title":"admin.create","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":17,"pid":15,"path":"admin/update","component":"admin/update","name":"admin.update","meta":{"title":"admin.update","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":18,"pid":15,"path":"admin/delete","component":"admin/delete","name":"admin.delete","meta":{"title":"admin.delete","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":19,"pid":15,"path":"admin/admin","component":"admin/admin","name":"admin.admin","meta":{"title":"admin.admin","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":20,"pid":15,"path":"admin/syncPermissions","component":"admin/syncPermissions","name":"admin.syncPermissions","meta":{"title":"admin.syncPermissions","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"path":"index","component":"admin/admins","name":"admin.admins","hidden":false,"meta":{"title":"admin.admins","icon":"el-icon-user-solid","roles":[1],"noCache":true,"breadcrumb":true,"affix":false}}],"redirect":"noRedirect"},{"id":26,"pid":0,"path":"/users","component":"layout/Layout","meta":{"title":"user.users","icon":"el-icon-user","roles":[1],"noCache":true,"breadcrumb":false,"affix":false},"hidden":false,"children":[{"id":27,"pid":26,"path":"user/create","component":"user/create","name":"user.create","meta":{"title":"user.create","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":28,"pid":26,"path":"user/update","component":"user/update","name":"user.update","meta":{"title":"user.update","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":29,"pid":26,"path":"user/delete","component":"user/delete","name":"user.delete","meta":{"title":"user.delete","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"id":30,"pid":26,"path":"user/user","component":"user/user","name":"user.user","meta":{"title":"user.user","icon":"icon","roles":[1],"noCache":true,"breadcrumb":true,"affix":false},"hidden":true,"children":[]},{"path":"index","component":"user/users","name":"user.users","hidden":false,"meta":{"title":"user.users","icon":"el-icon-user","roles":[1],"noCache":true,"breadcrumb":true,"affix":false}}],"redirect":"noRedirect"},{"path":"*","redirect":"/404","hidden":true}],"roles":["App\Models\Admin\1",1],"unreadNotificationCount":0,"permissions":[]}}}

中间件顺序问题

image

请问一下 这个两个中间件的顺序是在哪指定的吗 按照正常顺序 应该先执行jwt.auth 这个 然后在执行auth:admin 但是现在的顺序是 auth:admin -》jwt.auth 这样的 但是在kernel中也没有看到这个配置顺序 请教一下大佬是在哪指定的

`public/cert` 存储商户私钥及证书,可能存在泄漏风险

Ity/app/Models/Config.php

Lines 190 to 202 in b626989

$certificate = self::getCertificate(Storage::path('public/' . $fileinfo['filename'] . '/apiclient_cert.pem'));
// 微信支付平台证书
$wechatPayCertificate = self::getWechatPayCertificatePath($apiV3key, $certificate, Storage::path('public/' . $fileinfo['filename'] . '/apiclient_key.pem'), Storage::path('public/' . $fileinfo['filename']));
$wechatPayCertificateInfo = self::getCertificate(Storage::path('public/' . $fileinfo['filename'] . '/' . $wechatPayCertificate['serialNumber'] . '/wechatpay_cert.pem'));
Storage::deleteDirectory('public/cert');
Storage::makeDirectory('public/cert');
Storage::makeDirectory('public/cert/' . $wechatPayCertificateInfo['serialNumber']);
Storage::copy('public/' . $fileinfo['filename'] . '/apiclient_cert.pem', 'public/cert/apiclient_cert.pem');
Storage::copy('public/' . $fileinfo['filename'] . '/apiclient_key.pem', 'public/cert/apiclient_key.pem');
Storage::copy('public/' . $fileinfo['filename'] . '/' . $wechatPayCertificateInfo['serialNumber'] . '/wechatpay_cert.pem', 'public/cert/' . $wechatPayCertificateInfo['serialNumber'] . '/wechatpay_cert.pem');
Storage::deleteDirectory('public/' . $fileinfo['filename']);

web的根目录是在public,如果没做安全防范,恶意请求可以通过web方式直接下载到商户私钥文件cert/apiclient_key.pem,存在安全隐患。

项目用到了Redis,建议抛弃文件存储,商户私钥、商户证书、平台证书均可以以base64-string形式存储在库中,\WeChatPay\Rsa::from 支持无感加载,详情可参考:

从证书中提取公钥 详见 PHP openssl_x509_parse 返回值。

加载时仅需增加协议即形如 Rsa::from('public.spki://' . $i_am_a_base64_string_without_envelope, Rsa::KEY_TYPE_PUBLIC)

当然Rsa::from也支持原样以文件内容为字符串形式加载私钥及证书,详细用法可参考上述 RsaTest测试用例覆盖方法。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.