修改前端组件、后端添加jwt

This commit is contained in:
橙子
2021-10-14 20:29:07 +08:00
parent 40f34618a2
commit 9ce9d4ed98
17 changed files with 407 additions and 208 deletions

View File

@@ -4,8 +4,9 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Yi.Framework.Common; using Yi.Framework.Common.Helper;
using Yi.Framework.Common.Models; using Yi.Framework.Common.Models;
using Yi.Framework.Core;
using Yi.Framework.Interface; using Yi.Framework.Interface;
using Yi.Framework.Model.Models; using Yi.Framework.Model.Models;
@@ -33,9 +34,11 @@ namespace Yi.Framework.ApiMicroservice.Controllers
[HttpPost] [HttpPost]
public async Task<Result> Login(user _user) public async Task<Result> Login(user _user)
{ {
if( await _userService.Login(_user)) if (await _userService.Login(_user))
{ {
return Result.Success().SetData(new { _user, token = 123456789 }); _user.roles = await _userService.GetRolesByUser(_user);
var toke = MakeJwt.app(_user);
return Result.Success().SetData(new { user = new { _user.id, _user.username, _user.introduction, _user.icon, _user.nick }, toke });
} }
return Result.Error(); return Result.Error();
} }
@@ -45,7 +48,7 @@ namespace Yi.Framework.ApiMicroservice.Controllers
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
public Result Logout() public Result Logout()
{ {
return Result.Success(); return Result.Success();
} }
@@ -59,7 +62,7 @@ namespace Yi.Framework.ApiMicroservice.Controllers
[HttpPost] [HttpPost]
public async Task<Result> Register(user _user, string code) public async Task<Result> Register(user _user, string code)
{ {
if (code!=null) if (code != null)
{ {
await _userService.Register(_user); await _userService.Register(_user);
} }

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Yi.Framework.Common.Const
{
public class JwtConst
{
public const string SecurityKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI2a2EJ7m872v0afyoSDJT2o1+SitIeJSWtLJU8/Wz2m7gStexajkeD+Lka6DSTy8gt9UwfgVQo6uKjVLG5Ex7PiGOODVqAEghBuS7JzIYU5RvI543nNDAPfnJsas96mSA7L/mD7RTE2drj6hf3oZjJpMPZUQI/B1Qjb5H3K3PNwIDAQAB";
public const string Domain = "https://localhost:44329";
}
}

View File

@@ -5,7 +5,7 @@ using System.Net.Mail;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text; using System.Text;
namespace Yi.Framework.Common namespace Yi.Framework.Common.Helper
{ {
public class EmailHelper public class EmailHelper
{ {

View File

@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
namespace Yi.Framework.Core namespace Yi.Framework.Common.Helper
{ {
/// <summary> /// <summary>

View File

@@ -4,7 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace CC.ElectronicCommerce.Core namespace Yi.Framework.Common.Helper
{ {
public static class SnowflakeHelper public static class SnowflakeHelper
{ {

View File

@@ -0,0 +1,53 @@
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Common.Const;
using Yi.Framework.Model.Models;
using JwtRegisteredClaimNames = Microsoft.IdentityModel.JsonWebTokens.JwtRegisteredClaimNames;
namespace Yi.Framework.Core
{
public class MakeJwt
{
/// <summary>
/// user需关联所有roles
/// </summary>
/// <param name="_user"></param>
/// <returns></returns>
public static string app(user _user)
{
//通过查询权限,把所有权限加入进令牌中
List<Claim> claims = new List<Claim>();
claims.Add(new Claim(JwtRegisteredClaimNames.Nbf, $"{new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}"));
claims.Add(new Claim(JwtRegisteredClaimNames.Exp, $"{new DateTimeOffset(DateTime.Now.AddMinutes(30)).ToUnixTimeSeconds()}"));
claims.Add(new Claim(ClaimTypes.Name, _user.username));
claims.Add(new Claim(ClaimTypes.Sid, _user.id.ToString()));
foreach (var k in _user.roles)
{
claims.Add(new Claim(ClaimTypes.Role, k.role_name));
}
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtConst.SecurityKey));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: JwtConst.Domain,
audience: JwtConst.Domain,
claims: claims,
expires: DateTime.Now.AddMinutes(30),
signingCredentials: creds);
var tokenData = new JwtSecurityTokenHandler().WriteToken(token);
return tokenData;
}
}
}

View File

@@ -0,0 +1,39 @@
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.IO;
using System.Text;
using Yi.Framework.Common.Const;
namespace Yi.Framework.WebCore.MiddlewareExtend
{
/// <summary>
/// 通用跨域扩展
/// </summary>
public static class JwtExtension
{
public static IServiceCollection AddJwtService(this IServiceCollection services)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,//是否验证Issuer
ValidateAudience = true,//是否验证Audience
ValidateLifetime = true,//是否验证失效时间
ClockSkew = TimeSpan.FromDays(1),
ValidateIssuerSigningKey = true,//是否验证SecurityKey
ValidAudience = JwtConst.Domain,//Audience
ValidIssuer = JwtConst.Domain,//Issuer这两项和前面签发jwt的设置一致
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtConst.SecurityKey))//拿到SecurityKey
};
});
return services;
}
}
}

View File

@@ -0,0 +1,68 @@
<template>
<v-dialog v-model="dialog" persistent max-width="600px">
<template v-slot:activator="{ on, attrs }">
<v-btn color="primary" dark v-bind="attrs" v-on="on">
{{ headers }}
</v-btn>
</template>
<v-card>
<v-card-title>
<span class="text-h5">{{ headers }}</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12">
<v-combobox
v-model="select"
:items="items"
label="请点击选择"
multiple
chips
:item-text="itemText"
></v-combobox>
</v-col>
</v-row>
</v-container>
<small>*可多选</small>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="blue darken-1" text @click="dialog = false"> 关闭 </v-btn>
<v-btn color="blue darken-1" text @click="dialog = false"> 保存 </v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
export default {
props: {
headers: {
type: String
},
items:{
type:Array
},
itemText:{
type: String
}
},
name: "ccCombobox",
data() {
return {
dialog: false,
select: [],
};
},
watch:{
select:{//深度监听,可监听到对象、数组的变化
handler(val, oldVal){
this.$emit("select",val);
},
deep:true
}
},
};
</script>

View File

@@ -113,7 +113,7 @@
<script> <script>
import itemApi from "./TableApi.js"; import itemApi from "./TableApi.js";
export default { export default {
name: "Tables", name: "ccTable",
props: { props: {
defaultItem: { defaultItem: {
type: Object, type: Object,

View File

@@ -0,0 +1,43 @@
<template>
<v-treeview
selectable
:items="items"
:selection-type="selectionType"
v-model="selection"
return-object
open-all
hoverable
item-text="menu_name"
>
<template v-slot:append="{ item }">
<v-btn>{{ item.id }}</v-btn>
<v-btn>设置接口权限</v-btn>
</template>
</v-treeview>
</template>
<script>
export default {
name: "ccTreeview",
props: {
items: {
type: Array,
},
},
data: () => ({
selectionType: "leaf",
selection: [],
}),
watch:{
selection:{//深度监听,可监听到对象、数组的变化
handler(val, oldVal){
this.$emit("selection",val);
},
deep:true
}
},
methods:{
}
};
</script>

View File

@@ -249,6 +249,27 @@
mixins: [Proxyable], mixins: [Proxyable],
data: () => ({ data: () => ({
image:'https://demos.creative-tim.com/material-dashboard-pro/assets/img/sidebar-1.jpg',
mini: false,
drawer: null,
drawerImage: true,
gradient:
'rgba(228, 226, 226, 1), rgba(255, 255, 255, 0.7)',
images: [
'https://demos.creative-tim.com/material-dashboard-pro/assets/img/sidebar-1.jpg',
'https://demos.creative-tim.com/material-dashboard-pro/assets/img/sidebar-2.jpg',
'https://demos.creative-tim.com/material-dashboard-pro/assets/img/sidebar-3.jpg',
'https://demos.creative-tim.com/material-dashboard-pro/assets/img/sidebar-4.jpg',
],
gradients: [
'rgba(0, 0, 0, .7), rgba(0, 0, 0, .7)',
'rgba(228, 226, 226, 1), rgba(255, 255, 255, 0.7)',
'rgba(244, 67, 54, .8), rgba(244, 67, 54, .8)',
],
dark:null,
color: '#E91E63', color: '#E91E63',
colors: [ colors: [
'#9C27b0', '#9C27b0',

View File

@@ -1,34 +1,47 @@
<template> <template>
<v-card class="mx-auto" width="100%"> <v-card class="mx-auto" width="100%">
<v-btn>设置接口权限</v-btn> <ccTreeview :items="Menuitems"></ccTreeview>
<ccTable :defaultItem="defaultItem" :headers="headers" :axiosUrls="axiosUrls" ></ccTable>
</v-card> </v-card>
</template> </template>
<script> <script>
import ccTable from "@/components/Table.vue"
export default { export default {
components: {
ccTable
},
data: () => ({ data: () => ({
axiosUrls:{ Menuitems: [
get:"role/getrole", {
update:"role/updaterole", id: 1,
del:"role/delListrole", menu_name: "用户角色管理",
add:"role/addrole" children: [
}, {
headers: [ id: 2,
{text: "编号",align: "start",value: "id"}, menu_name: "用户管理",
{ text: "角色名", value: "role_name", sortable: false }, children: [
{ text: "简介", value: "introduce", sortable: false }, {
{ text: "操作", value: "actions", sortable: false } id: 4,
menu_name: "添加",
children: [],
},
{
id: 5,
menu_name: "修改",
children: [],
},
{
id: 7,
menu_name: "删除",
children: [],
},
{
id: 8,
menu_name: "查询",
children: [],
},
],
},
{ id: 3, menu_name: "角色管理" },
],
},
], ],
defaultItem: { })
role_name: "test",
introduce: "用于测试",
},
}),
}; };
</script> </script>

View File

@@ -5,11 +5,7 @@
</template> </template>
<script> <script>
import ccTable from "@/components/Table.vue"
export default { export default {
components: {
ccTable
},
data: () => ({ data: () => ({
axiosUrls:{ axiosUrls:{
get:"role/getrole", get:"role/getrole",

View File

@@ -1,18 +1,12 @@
<template> <template>
<v-card class="mx-auto" width="100%"> <v-card class="mx-auto" width="100%">
<ccTable :defaultItem="defaultItem" :headers="headers" :axiosUrls="axiosUrls" > <ccTable :defaultItem="defaultItem" :headers="headers" :axiosUrls="axiosUrls" >
</ccTable> </ccTable>
</v-card> </v-card>
</template> </template>
<script> <script>
import ccTable from "@/components/Table.vue"
export default { export default {
components: {
ccTable
},
data: () => ({ data: () => ({
axiosUrls:{ axiosUrls:{
get:"role/getrole", get:"role/getrole",

View File

@@ -1,148 +1,87 @@
<template> <template>
<v-card class="mx-auto" width="100%">
<v-row> <v-row>
<v-col cols="6"> <v-col cols="12" md="4" lg="4">
<v-list <v-card class="mx-auto" width="100%">
flat <v-treeview
subheader selectable
three-line :items="RoleItems"
> v-model="selectionRole"
<v-subheader>General</v-subheader> return-object
open-all
hoverable
item-text="role_name"
>
</v-treeview>
</v-card>
</v-col>
<v-list-item-group <v-col cols="12" md="8" lg="8">
v-model="settings" <v-card class="mx-auto" width="100%">
multiple <v-treeview
active-class="" selectable
:items="Menuitems"
selection-type="leaf"
v-model="selectionMenu"
return-object
open-all
hoverable
item-text="menu_name"
>
<template v-slot:append="{ item }">
<v-btn>{{ item.id }}</v-btn>
</template>
</v-treeview>
</v-card></v-col
> >
<v-list-item>
<template v-slot:default="{ active }">
<v-list-item-action>
<v-checkbox :input-value="active"></v-checkbox>
</v-list-item-action>
<v-list-item-content> </v-row>
<v-list-item-title>Notifications</v-list-item-title>
<v-list-item-subtitle>Notify me about updates to apps or games that I downloaded</v-list-item-subtitle>
</v-list-item-content>
</template>
</v-list-item>
<v-list-item>
<template v-slot:default="{ active }">
<v-list-item-action>
<v-checkbox :input-value="active"></v-checkbox>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>Sound</v-list-item-title>
<v-list-item-subtitle>Auto-update apps at any time. Data charges may apply</v-list-item-subtitle>
</v-list-item-content>
</template>
</v-list-item>
<v-list-item>
<template v-slot:default="{ active }">
<v-list-item-action>
<v-checkbox :input-value="active"></v-checkbox>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>Auto-add widgets</v-list-item-title>
<v-list-item-subtitle>Automatically add home screen widgets when downloads complete</v-list-item-subtitle>
</v-list-item-content>
</template>
</v-list-item>
</v-list-item-group>
</v-list>
</v-col>
<v-col cols="6"> <v-treeview
selectable
:items="items"
></v-treeview></v-col>
</v-row>
</v-card>
</template> </template>
<script> <script>
export default { export default {
data: () => ({ data: () => ({
items: [ selectionMenu: [],
{ selectionRole: [],
id: 1, RoleItems: [
name: 'Applications :', { id: 1, role_name: "管理员", sex: "测试" },
children: [ { id: 2, role_name: "超级管理员", sex: "测试" },
{ id: 2, name: 'Calendar : app' }, ],
{ id: 3, name: 'Chrome : app' }, Menuitems: [
{ id: 4, name: 'Webstorm : app' }, {
], id: 1,
}, menu_name: "用户角色管理",
{ children: [
id: 5, {
name: 'Documents :', id: 2,
children: [ menu_name: "用户管理",
{ children: [
id: 6, {
name: 'vuetify :', id: 4,
children: [ menu_name: "添加",
{ children: [],
id: 7, },
name: 'src :', {
children: [ id: 5,
{ id: 8, name: 'index : ts' }, menu_name: "修改",
{ id: 9, name: 'bootstrap : ts' }, children: [],
], },
}, {
], id: 7,
}, menu_name: "删除",
{ children: [],
id: 10, },
name: 'material2 :', {
children: [ id: 8,
{ menu_name: "查询",
id: 11, children: [],
name: 'src :', },
children: [ ],
{ id: 12, name: 'v-btn : ts' }, },
{ id: 13, name: 'v-card : ts' }, { id: 3, menu_name: "角色管理" },
{ id: 14, name: 'v-window : ts' }, ],
], },
}, ],
], }),
}, };
],
},
{
id: 15,
name: 'Downloads :',
children: [
{ id: 16, name: 'October : pdf' },
{ id: 17, name: 'November : pdf' },
{ id: 18, name: 'Tutorial : html' },
],
},
{
id: 19,
name: 'Videos :',
children: [
{
id: 20,
name: 'Tutorials :',
children: [
{ id: 21, name: 'Basic layouts : mp4' },
{ id: 22, name: 'Advanced techniques : mp4' },
{ id: 23, name: 'All about app : dir' },
],
},
{ id: 24, name: 'Intro : mov' },
{ id: 25, name: 'Conference introduction : avi' },
],
},
],
}),
}
</script> </script>

View File

@@ -1,41 +1,48 @@
<template> <template>
<v-card class="mx-auto" width="100%"> <v-card class="mx-auto" width="100%">
<v-btn>设置角色</v-btn> {{select}}
<ccTable :defaultItem="defaultItem" :headers="headers" :axiosUrls="axiosUrls" ></ccTable> <ccCombobox headers='设置角色' :items="items" @select="getSelect" itemText="role_name"></ccCombobox>
</v-card> <ccTable
:defaultItem="defaultItem"
:headers="headers"
:axiosUrls="axiosUrls"
></ccTable>
</v-card>
</template> </template>
<script> <script>
import ccTable from "@/components/Table.vue"
export default { export default {
components: { methods:{
ccTable getSelect(data){
this.select=data;
}
}, },
data: () => ({ data: () => ({
axiosUrls:{ select:[],
get:"user/getuser", items: [{id:1,role_name:"管理员"},{id:1,role_name:"超级管理员"}],
update:"user/updateuser", axiosUrls: {
del:"user/delListuser", get: "user/getuser",
add:"user/adduser" update: "user/updateuser",
}, del: "user/delListuser",
add: "user/adduser",
},
headers: [ headers: [
{text: "编号",align: "start",value: "id"}, { text: "编号", align: "start", value: "id" },
{ text: "用户名", value: "username", sortable: false }, { text: "用户名", value: "username", sortable: false },
{ text: "密码", value: "password", sortable: false }, { text: "密码", value: "password", sortable: false },
{ text: "图标", value: "icon", sortable: false }, { text: "图标", value: "icon", sortable: false },
{ text: "昵称", value: "nick", sortable: true }, { text: "昵称", value: "nick", sortable: true },
{ text: "邮箱", value: "email", sortable: true }, { text: "邮箱", value: "email", sortable: true },
{ text: "IP", value: "ip", sortable: false }, { text: "IP", value: "ip", sortable: false },
{ text: "年龄", value: "age", sortable: false }, { text: "年龄", value: "age", sortable: false },
{ text: "操作", value: "actions", sortable: false }, { text: "操作", value: "actions", sortable: false },
], ],
defaultItem: { defaultItem: {
username: "test", username: "test",
password: "123", password: "123",
icon: "mdi-lock", icon: "mdi-lock",
nick:"橙子", nick: "橙子",
age:18 age: 18,
} },
}), }),
}; };
</script> </script>

View File

@@ -1,3 +1,14 @@
<template> <template>
<div>首页</div> <div>
<MaterialCard title="首页卡片" subtitle="微软Microsoft是一家美国跨国科技企业由比尔·盖茨和保罗·艾伦于1975年4月4日创立。" heading="头部" color='#E91E63' :fullHeader='false' icon='mdi-view-dashboard'></MaterialCard>
<MaterialCharCard></MaterialCharCard>
<MaterialSnackbar></MaterialSnackbar>
<MaterialStatCard value="微软Microsoft是一家美国跨国科技企业由比尔·盖茨和保罗·艾伦于1975年4月4日创立。">
<template v-slot>
还有什么呢
</template>
</MaterialStatCard>
</div>
</template> </template>