Browse Source

fix:修改登录token生成,解决审计日志没有用户名和用户ID

old-3.0
WangJunZzz 5 years ago
parent
commit
7db96b0dfd
  1. 10
      content/aspnetcore/host/CompanyName.ProjectName.HttpApi.Host/CompanyNameProjectNameHttpApiHostModule.cs
  2. 73
      content/aspnetcore/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/DefaultHttpExceptionStatusCodeFinder.cs
  3. 2
      content/aspnetcore/host/CompanyName.ProjectName.HttpApi.Host/Properties/launchSettings.json
  4. 6
      content/aspnetcore/host/CompanyName.ProjectName.HttpApi.Host/appsettings.json
  5. 2
      content/aspnetcore/src/CompanyName.ProjectName.Application.Contracts/Users/Dtos/LoginInputDto.cs
  6. 14
      content/aspnetcore/src/CompanyName.ProjectName.Application/Users/LoginAppService.cs
  7. 2
      content/aspnetcore/tools/CompanyName.ProjectName.DbMigrator/appsettings.json
  8. 1
      content/vue/.husky/.gitignore
  9. 7
      content/vue/package.json
  10. 35
      content/vue/src/layouts/default/header/index.vue
  11. 4
      content/vue/src/locales/lang/en/common.ts
  12. 1
      content/vue/src/locales/lang/en/routes/admin.ts
  13. 2
      content/vue/src/locales/lang/en/sys/login.ts
  14. 4
      content/vue/src/locales/lang/zh_CN/common.ts
  15. 1
      content/vue/src/locales/lang/zh_CN/routes/admin.ts
  16. 2
      content/vue/src/locales/lang/zh_CN/sys/login.ts
  17. 12
      content/vue/src/services/ServiceProxyBase.ts
  18. 4
      content/vue/src/views/admin/audits/audit.ts
  19. 1
      content/vue/src/views/admin/roles/PermissionAbpRole.vue
  20. 8
      content/vue/src/views/admin/users/AbpUser.vue
  21. 5
      content/vue/yarn.lock

10
content/aspnetcore/host/CompanyName.ProjectName.HttpApi.Host/CompanyNameProjectNameHttpApiHostModule.cs

@ -108,18 +108,11 @@ namespace CompanyNameProjectName
} }
app.UseCorrelationId(); app.UseCorrelationId();
app.UseVirtualFiles(); app.UseStaticFiles();
app.UseRouting(); app.UseRouting();
app.UseCors(DefaultCorsPolicyName); app.UseCors(DefaultCorsPolicyName);
app.UseAuthentication(); app.UseAuthentication();
app.UseJwtTokenMiddleware(); app.UseJwtTokenMiddleware();
//if (MultiTenancyConsts.IsEnabled)
//{
// app.UseMultiTenancy();
//}
//app.UseIdentityServer();
app.UseAuthorization(); app.UseAuthorization();
app.UseSwagger(); app.UseSwagger();
@ -161,6 +154,7 @@ namespace CompanyNameProjectName
{ {
options.IsEnabled = true; options.IsEnabled = true;
options.EntityHistorySelectors.AddAllEntities(); options.EntityHistorySelectors.AddAllEntities();
options.ApplicationName = "CompanyName.ProjectName";
}); });
} }

73
content/aspnetcore/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/DefaultHttpExceptionStatusCodeFinder.cs

@ -0,0 +1,73 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using System;
using System.Net;
using Volo.Abp;
using Volo.Abp.AspNetCore.ExceptionHandling;
using Volo.Abp.Authorization;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities;
using Volo.Abp.ExceptionHandling;
using Volo.Abp.Validation;
namespace CompanyNameProjectName.Extensions.Filters
{
[Dependency(ReplaceServices = true)]
public class DefaultHttpExceptionStatusCodeFinder : IHttpExceptionStatusCodeFinder, ITransientDependency
{
protected AbpExceptionHttpStatusCodeOptions Options { get; }
public DefaultHttpExceptionStatusCodeFinder(
IOptions<AbpExceptionHttpStatusCodeOptions> options)
{
Options = options.Value;
}
public HttpStatusCode GetStatusCode(HttpContext httpContext, Exception exception)
{
if (exception is IHasHttpStatusCode exceptionWithHttpStatusCode &&
exceptionWithHttpStatusCode.HttpStatusCode > 0)
{
return (HttpStatusCode)exceptionWithHttpStatusCode.HttpStatusCode;
}
if (exception is IHasErrorCode exceptionWithErrorCode &&
!exceptionWithErrorCode.Code.IsNullOrWhiteSpace())
{
if (Options.ErrorCodeToHttpStatusCodeMappings.TryGetValue(exceptionWithErrorCode.Code, out var status))
{
return status;
}
}
if (exception is AbpAuthorizationException)
{
return HttpStatusCode.Forbidden;
}
//TODO: Handle SecurityException..?
if (exception is AbpValidationException)
{
return HttpStatusCode.BadRequest;
}
if (exception is EntityNotFoundException)
{
return HttpStatusCode.NotFound;
}
if (exception is NotImplementedException)
{
return HttpStatusCode.NotImplemented;
}
if (exception is IBusinessException)
{
return HttpStatusCode.InternalServerError;
}
return HttpStatusCode.InternalServerError;
}
}
}

2
content/aspnetcore/host/CompanyName.ProjectName.HttpApi.Host/Properties/launchSettings.json

@ -7,7 +7,7 @@
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
}, },
"applicationUrl": "http://localhost:50010/" "applicationUrl": "http://localhost:50010"
} }
} }
} }

6
content/aspnetcore/host/CompanyName.ProjectName.HttpApi.Host/appsettings.json

@ -31,12 +31,12 @@
} }
}, },
"ConnectionStrings": { "ConnectionStrings": {
"Default": "Data Source=mysql.platform.development.cn;Database=CompanyNameProjectName;uid=root;pwd=mysql@dmin;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true" "Default": "Data Source=localhost;Database=CompanyNameProjectName;uid=root;pwd=mypassword;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true"
}, },
"Cache": { "Cache": {
"Redis": { "Redis": {
"ConnectionString": "redis.platform.development.cn,password=OD5VbzIuAWsHOZV5ncYx9xaDsAMsKXn7", "ConnectionString": "localhost,password=mypassword",
"DatabaseId": 234 "DatabaseId": 1
} }
}, },
"AuthServer": { "AuthServer": {

2
content/aspnetcore/src/CompanyName.ProjectName.Application.Contracts/Users/Dtos/LoginInputDto.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using Volo.Abp.Auditing;
namespace CompanyNameProjectName.Dtos.Users namespace CompanyNameProjectName.Dtos.Users
{ {
@ -17,6 +18,7 @@ namespace CompanyNameProjectName.Dtos.Users
/// <summary> /// <summary>
/// 密码 /// 密码
/// </summary> /// </summary>
[DisableAuditing]
public string Password { get; set; } public string Password { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)

14
content/aspnetcore/src/CompanyName.ProjectName.Application/Users/LoginAppService.cs

@ -14,6 +14,7 @@ using System.Threading.Tasks;
using Volo.Abp; using Volo.Abp;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
using Volo.Abp.Identity; using Volo.Abp.Identity;
using Volo.Abp.Security.Claims;
namespace CompanyNameProjectName.Users namespace CompanyNameProjectName.Users
{ {
@ -72,12 +73,13 @@ namespace CompanyNameProjectName.Users
var key = Encoding.ASCII.GetBytes(_jwtOptions.SecurityKey); var key = Encoding.ASCII.GetBytes(_jwtOptions.SecurityKey);
var claims = new List<Claim> { var claims = new List<Claim> {
new Claim(JwtClaimTypes.Audience, _jwtOptions.Audience), new Claim(JwtClaimTypes.Audience, _jwtOptions.Audience),
new Claim(JwtClaimTypes.Issuer, _jwtOptions.Issuer), new Claim(JwtClaimTypes.Issuer, _jwtOptions.Issuer),
new Claim(JwtClaimTypes.Subject, user.Id.ToString()), new Claim(AbpClaimTypes.UserId, user.Id.ToString()),
new Claim(JwtClaimTypes.Name, user.Name), new Claim(AbpClaimTypes.Name, user.Name),
new Claim(JwtClaimTypes.Email, user.Email), new Claim(AbpClaimTypes.UserName, user.UserName),
new Claim("TenantId", user.TenantId.ToString()) new Claim(AbpClaimTypes.Email, user.Email),
new Claim(AbpClaimTypes.TenantId, user.TenantId.ToString())
}; };
foreach (var item in roles) foreach (var item in roles)

2
content/aspnetcore/tools/CompanyName.ProjectName.DbMigrator/appsettings.json

@ -1,5 +1,5 @@
{ {
"ConnectionStrings": { "ConnectionStrings": {
"Default": "Data Source=mysql.platform.development.cn;Database=CompanyNameProjectName;uid=root;pwd=mysql@dmin;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true" "Default": "Data Source=localhost;Database=CompanyNameProjectName;uid=root;pwd=mypassword;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true"
} }
} }

1
content/vue/.husky/.gitignore

@ -1 +0,0 @@
_

7
content/vue/package.json

@ -23,14 +23,12 @@
"lint:eslint": "eslint \"{src,mock}/**/*.{vue,ts,tsx}\" --fix", "lint:eslint": "eslint \"{src,mock}/**/*.{vue,ts,tsx}\" --fix",
"lint:prettier": "prettier --write --loglevel warn \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"", "lint:prettier": "prettier --write --loglevel warn \"src/**/*.{js,json,tsx,css,less,scss,vue,html,md}\"",
"lint:stylelint": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/", "lint:stylelint": "stylelint --fix \"**/*.{vue,less,postcss,css,scss}\" --cache --cache-location node_modules/.cache/stylelint/",
"lint:lint-staged": "lint-staged -c ./.husky/lintstagedrc.js",
"lint:pretty": "pretty-quick --staged", "lint:pretty": "pretty-quick --staged",
"test:gzip": "http-server dist --cors --gzip -c-1", "test:gzip": "http-server dist --cors --gzip -c-1",
"test:br": "http-server dist --cors --brotli -c-1", "test:br": "http-server dist --cors --brotli -c-1",
"reinstall": "rimraf yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap", "reinstall": "rimraf yarn.lock && rimraf package.lock.json && rimraf node_modules && npm run bootstrap",
"install:husky": "is-ci || husky install", "gen:icon": "esno ./build/generate/icon/index.ts"
"gen:icon": "esno ./build/generate/icon/index.ts",
"postinstall": "npm run install:husky"
}, },
"dependencies": { "dependencies": {
"@iconify/iconify": "^2.0.0-rc.6", "@iconify/iconify": "^2.0.0-rc.6",
@ -90,7 +88,6 @@
"esno": "^0.5.0", "esno": "^0.5.0",
"fs-extra": "^9.1.0", "fs-extra": "^9.1.0",
"http-server": "^0.12.3", "http-server": "^0.12.3",
"husky": "^6.0.0",
"inquirer": "^8.0.0", "inquirer": "^8.0.0",
"is-ci": "^3.0.0", "is-ci": "^3.0.0",
"less": "^4.1.1", "less": "^4.1.1",

35
content/vue/src/layouts/default/header/index.vue

@ -55,7 +55,7 @@
</Header> </Header>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, unref, computed } from 'vue'; import { defineComponent, unref, computed,onMounted } from 'vue';
import { propTypes } from '/@/utils/propTypes'; import { propTypes } from '/@/utils/propTypes';
@ -80,6 +80,8 @@
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import { useLocale } from '/@/locales/useLocale'; import { useLocale } from '/@/locales/useLocale';
import { useUserStoreWidthOut } from '/@/store/modules/user';
import jwt_decode from 'jwt-decode';
export default defineComponent({ export default defineComponent({
name: 'LayoutHeader', name: 'LayoutHeader',
@ -173,6 +175,37 @@
return unref(getSplit) ? MenuModeEnum.HORIZONTAL : null; return unref(getSplit) ? MenuModeEnum.HORIZONTAL : null;
}); });
function timestampToTime(timestamp) {
var date = new Date(timestamp * 1000); //10*1000131000
var Y = date.getFullYear() + '-';
var M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-';
var D = date.getDate() + ' ';
var h = date.getHours() + ':';
var m = date.getMinutes() + ':';
var s = date.getSeconds();
return Y + M + D + h + m + s;
}
const checkLoginExpired = () => {
setInterval(() => {
const userStore = useUserStoreWidthOut();
const token = userStore.getToken;
if (!token) {
userStore.logout(true);
} else {
const decoded: any = jwt_decode(token);
let tokenExpiredTime = timestampToTime(decoded.exp);
var tokenExpiredTimeFormat = new Date(Date.parse(tokenExpiredTime));
const currentTime = new Date();
if (currentTime >= tokenExpiredTimeFormat) {
userStore.logout(true);
}
}
}, 1000 * 60);
};
onMounted(() => {
checkLoginExpired();
});
return { return {
prefixCls, prefixCls,
getHeaderClass, getHeaderClass,

4
content/vue/src/locales/lang/en/common.ts

@ -23,5 +23,7 @@ export default {
operationSuccess: 'Operation Success', operationSuccess: 'Operation Success',
operationFail: 'Operation Fail', operationFail: 'Operation Fail',
authorityText: 'Login expired', authorityText: 'Login expired',
systemErrorText: 'System Error' systemErrorText: 'System Error',
enable:"Enable",
disable:"Disable"
}; };

1
content/vue/src/locales/lang/en/routes/admin.ts

@ -33,4 +33,5 @@ export default {
audit_url: "URL", audit_url: "URL",
audit_entityInfo: "EntityInformation", audit_entityInfo: "EntityInformation",
audit_message: "Entity Message", audit_message: "Entity Message",
audit_applicationName:"ApplicationName"
}; };

2
content/vue/src/locales/lang/en/sys/login.ts

@ -7,7 +7,7 @@ export default {
forgetFormTitle: 'Reset password', forgetFormTitle: 'Reset password',
signInTitle: 'Abp Vnext Pro', signInTitle: 'Abp Vnext Pro',
signInDesc: '基于DotNet Core5.0,Abp Vnext 4.2的开箱即用的后台模板 ', signInDesc: '基于DotNet Core5.0,Abp Vnext 4.3的开箱即用的后台模板 ',
policy: 'I agree to the xxx Privacy Policy', policy: 'I agree to the xxx Privacy Policy',
scanSign: `scanning the code to complete the login`, scanSign: `scanning the code to complete the login`,

4
content/vue/src/locales/lang/zh_CN/common.ts

@ -22,5 +22,7 @@ export default {
operationSuccess: '操作成功', operationSuccess: '操作成功',
operationFail: '操作失败', operationFail: '操作失败',
authorityText: '登陆过期', authorityText: '登陆过期',
systemErrorText: '系统异常' systemErrorText: '系统异常',
enable:"启用",
disable:"禁用"
}; };

1
content/vue/src/locales/lang/zh_CN/routes/admin.ts

@ -31,4 +31,5 @@ export default {
audit_url: "Url地址", audit_url: "Url地址",
audit_entityInfo: "实体信息", audit_entityInfo: "实体信息",
audit_message: "实体信息", audit_message: "实体信息",
audit_applicationName:"应用名称"
}; };

2
content/vue/src/locales/lang/zh_CN/sys/login.ts

@ -7,7 +7,7 @@ export default {
forgetFormTitle: '重置密码', forgetFormTitle: '重置密码',
signInTitle: 'Abp Vnext Pro', signInTitle: 'Abp Vnext Pro',
signInDesc: '基于DotNet Core5.0,Abp Vnext 4.2的开箱即用的后台模板 ', signInDesc: '基于DotNet Core5.0,Abp Vnext 4.3的开箱即用的后台模板 ',
policy: '我同意xxx隐私政策', policy: '我同意xxx隐私政策',
scanSign: `扫码后点击"确认",即可完成登录`, scanSign: `扫码后点击"确认",即可完成登录`,

12
content/vue/src/services/ServiceProxyBase.ts

@ -4,7 +4,7 @@ import { useUserStoreWidthOut } from '/@/store/modules/user';
import router from '/@/router'; import router from '/@/router';
import { PageEnum } from '/@/enums/pageEnum'; import { PageEnum } from '/@/enums/pageEnum';
import { useI18n } from '/@/hooks/web/useI18n'; import { useI18n } from '/@/hooks/web/useI18n';
import { Modal } from 'ant-design-vue';
export class ServiceProxyBase { export class ServiceProxyBase {
protected transformOptions(options: AxiosRequestConfig) { protected transformOptions(options: AxiosRequestConfig) {
@ -20,14 +20,16 @@ export class ServiceProxyBase {
return Promise.resolve(options); return Promise.resolve(options);
} }
protected transformResult(url: string, response: AxiosResponse, processor: (response: AxiosResponse) => Promise<any>): Promise<any> { protected transformResult(_url: string, response: AxiosResponse, processor: (response: AxiosResponse) => Promise<any>): Promise<any> {
const { t } = useI18n();
if (response.status == 401 || response.status == 403 || response.status == 302) { if (response.status == 401 || response.status == 403 || response.status == 302) {
const { t } = useI18n();
message.error(t('common.authorityText')); message.error(t('common.authorityText'));
router.replace(PageEnum.BASE_LOGIN) router.replace(PageEnum.BASE_LOGIN)
} else if (response.status >= 500) { } else if (response.status >= 500) {
message.error(response.data.error.message) Modal.error({
title: '请求异常',
content: response.data.error.message,
});
} }
return processor(response); return processor(response);
} }

4
content/vue/src/views/admin/audits/audit.ts

@ -252,6 +252,10 @@ export const searchFormSchema: FormSchema[] = [
} }
] ]
export const tableColumns: BasicColumn[] = [ export const tableColumns: BasicColumn[] = [
{
title: t('routes.admin.audit_applicationName'),
dataIndex: 'applicationName',
},
{ {
title: t('routes.admin.audit_httpRequest'), title: t('routes.admin.audit_httpRequest'),
dataIndex: 'httpMethod', dataIndex: 'httpMethod',

1
content/vue/src/views/admin/roles/PermissionAbpRole.vue

@ -101,6 +101,7 @@
}; };
const submitRolePermisstionAsync = async () => { const submitRolePermisstionAsync = async () => {
debugger;
let request: UpdateRolePermissionsDto = new UpdateRolePermissionsDto(); let request: UpdateRolePermissionsDto = new UpdateRolePermissionsDto();
request.updatePermissionsDto = new UpdatePermissionsDto(); request.updatePermissionsDto = new UpdatePermissionsDto();

8
content/vue/src/views/admin/users/AbpUser.vue

@ -11,8 +11,8 @@
</a-button> </a-button>
</template> </template>
<template #lockoutEnabled="{ record }"> <template #lockoutEnabled="{ record }">
<Tag :color="record.lockoutEnabled ? 'red' : 'green'"> <Tag :color="record.lockoutEnabled && record.lockoutEnd!=null ? 'red' : 'green'">
{{ record.lockoutEnabled ? '已锁定' : '未锁定' }} {{ record.lockoutEnabled && record.lockoutEnd!=null ? t('common.enable') : t('common.disable') }}
</Tag> </Tag>
</template> </template>
<template #action="{ record }"> <template #action="{ record }">
@ -40,7 +40,7 @@
@click="handleLock(record)" @click="handleLock(record)"
v-auth="'AbpIdentity.Users.Lock'" v-auth="'AbpIdentity.Users.Lock'"
> >
{{ record.lockoutEnabled ? '启用' : '禁用' }} {{ record.lockoutEnabled ? t('common.enable') : t('common.disable') }}
</a-button> </a-button>
</template> </template>
</BasicTable> </BasicTable>
@ -103,7 +103,7 @@
canResize: false, canResize: false,
showIndexColumn: true, showIndexColumn: true,
actionColumn: { actionColumn: {
width: 150, width: 200,
title: t('common.action'), title: t('common.action'),
dataIndex: 'action', dataIndex: 'action',
slots: { slots: {

5
content/vue/yarn.lock

@ -4863,11 +4863,6 @@ human-signals@^2.1.0:
resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" resolved "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
husky@^6.0.0:
version "6.0.0"
resolved "https://registry.npmjs.org/husky/-/husky-6.0.0.tgz#810f11869adf51604c32ea577edbc377d7f9319e"
integrity sha512-SQS2gDTB7tBN486QSoKPKQItZw97BMOd+Kdb6ghfpBc0yXyzrddI0oDV5MkDAbuB4X2mO3/nj60TRMcYxwzZeQ==
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4:
version "0.4.24" version "0.4.24"
resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"

Loading…
Cancel
Save