一、后端接口:WebApi
1.appsettings.json文件
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"Authentication": {
"SecretKey": "JianKeEducationCRMAPI",
"Issuer": "******",
"Audience": "******"
},
"AllowedHosts": "*"
}
2.Startup.cs
需要的命名空间
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
ConfigureServices需要修改
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
var secretByte = Encoding.UTF8.GetBytes(Configuration["Authentication:SecretKey"]);
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidIssuer = Configuration["Authentication:Issuer"],
ValidateAudience = true,
ValidAudience = Configuration["Authentication:Audience"],
ValidateLifetime = true,
IssuerSigningKey = new SymmetricSecurityKey(secretByte)
};
});
Configure里必须有
app.UseAuthorization();
3.登录方法
[ApiController]
[Route("api/[controller]/[action]")]
public class UserController : ControllerBase
{
private readonly IConfiguration _configuration;
public UserController(IConfiguration configuration)
{
_configuration = configuration;
}
[HttpPost]
public JsonResult Login([FromBody] UserModel userModel)
//public string Login(string userName, string password)
{
if (userModel.userName=="1" && userModel.password=="1")
{
//var Permission = "Permission";
var userId = "1";
//验证用户名密码
//创建JWT
// header
var signingAlgorithm = SecurityAlgorithms.HmacSha256;
// payload
var claims = new List<Claim>
{
// sub
new Claim(JwtRegisteredClaimNames.Sub,userId),
//new Claim(ClaimTypes.Role, "Admin")
};
// signiture
var secretByte = Encoding.UTF8.GetBytes(_configuration["Authentication:SecretKey"]);//Authentication
//var secretByte = Encoding.UTF8.GetBytes("dengfenglaiSecretKey");
var signingKey = new SymmetricSecurityKey(secretByte);
var signingCredentials = new SigningCredentials(signingKey, signingAlgorithm);
var token = new JwtSecurityToken(
//颁发者
issuer: _configuration["Authentication:Issuer"],//"dengfneglai", //
//接收者
audience: _configuration["Authentication:Audience"],//"zhuifengqu", //
//自定义参数
claims,
notBefore: DateTime.UtcNow,
//过期时间
expires: DateTime.UtcNow.AddDays(1),
//expires: DateTime.UtcNow.AddMinutes(2),
//签名证书
signingCredentials
);
var tokenStr = new JwtSecurityTokenHandler().WriteToken(token);
return new JsonResult(new JsonApi(tokenStr));
}
else
{
return new JsonResult(new JsonApi() { Success = false, Error = "用户名或密码错误", Code = "401" });
}
}
[Serializable]
public class UserModel
{
public string userName { get; set; }
public string password { get; set; }
}
}
4.登录成功后需要跳转个人中心页面,调用个人中心方法
[Authorize(AuthenticationSchemes = "Bearer")]
[ApiController]
[Route("api/[controller]/[action]")]
public class UserInfoController : ControllerBase
{
[HttpGet]
public IActionResult GetUserInfoById([FromQuery] int id)
{
var entityUserInfo = new UserInfo() {Id=id };
var json = JsonSerializeHelper.Serialize(entityUserInfo);
return new JsonResult(new JsonApi(json));
}
}
public class UserInfo
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Description { get; set; }
}
二、前端Vue
1.登录页面
<template>
<div id="App" class="login">
{{this.$store.state.name}}
登录名:<input v-model="userName" type="text" placeholder="请输入用户名"/>
密码:<input v-model="password" type="password" placeholder="请输入密码"/>
<!-- <input v-model="message" /> -->
<button v-on:click="LoginClick">登录</button>
</div>
</template>
<script lang='ts'>
import Vue, { toRefs, reactive, defineComponent, createApp } from 'vue'
import axios from 'axios'
import router from '@/router/index'
interface userData{
userName:string
password:string
LoginClick:()=>void
}
export default defineComponent({
setup () {
const data = reactive<userData>({
userName: '',
password: '',
LoginClick: async () => {
if (!data.userName) { alert('请输入用户名'); return }
if (!data.password) { alert('请输入密码'); return }
const result: any = await axios.post(process.env.VUE_APP_BASE_API + '/user/Login', {
userName: data.userName,
password: data.password
})
if (result.success === true) {
console.log(result, 'result')
localStorage.setItem('Authentication', result.data)
router.push({ path: '/UserCenter' })
} else {
alert(result.error)
}
}
})
return {
...toRefs(data)
}
}
})
</script>
2.个人中心页
<template>
<div id="App">
个人中心
</div>
</template>
<script lang=ts>
import { createApp, defineComponent, reactive, toRefs } from 'vue'
import axios from 'axios'
// import baseUrl from 'baseUrl'
interface userData{
userId:string
userName:string
password:string
GetUserInfoById:()=>void
}
export default defineComponent({
name: 'userCenter',
setup () {
const data = reactive<userData>({
userId: '1',
userName: '',
password: '',
GetUserInfoById: async () => {
const result:any = await axios.get(process.env.VUE_APP_BASE_API + '/UserInfo/GetUserInfoById?id=1', {
// id: data.userId
// headers: {
// Authorization: 'Bearer ' + localStorage.getItem('Authentication')
// }
})
if (result.success === true) {
console.log(result, 'result')
} else {
alert(result.error)
}
}
})
return {
...toRefs(data)
}
},
mounted: function () {
this.GetUserInfoById()
}
})
// console.log(localStorage.getItem('token'), 'userCenter.token')
</script>
3.main.ts
// import { config } from '@vue/test-utils'
import axios from 'axios'
import { createApp } from 'vue'
import App from './App.vue'
import './registerServiceWorker'
import router from './router'
import store from './store'
// 设置axios请求头加入token(Authentication)
axios.interceptors.request.use(config => {
// if (config.push === '/') {} else {
if (localStorage.getItem('Authentication')) {
// 在请求头加入token(Authentication),名字要和后端接收请求头的token(Authentication)名字一样
config.headers.Authorization = 'Bearer ' + localStorage.getItem('Authentication')
console.log('Bearer ' + localStorage.getItem('Authentication'))
}
// }
return config
}, error => {
return Promise.reject(error)
})
//= ============================
// 响应回来token是否过期
axios.interceptors.response.use(res => {
const data = res.data
console.log('响应回来:' + data.code)
// 和后端token失效返回码约定403
if (data.code === '403') {
alert('身份已失效')
localStorage.removeItem('token')
router.push({ name: 'Login' })
} else {
return data
}
}, error => {
return Promise.reject(error)
}
)
createApp(App).use(store).use(router).mount('#app')
4.router的index.ts
import { createRouter, createWebHashHistory, RouteRecordRaw } from 'vue-router'
import Home from '../views/Home.vue'
import Login from '../views/Login.vue'
// import UserCenter from '..views/UserCenter.vue'
const routes: Array<RouteRecordRaw> = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/Login',
name: 'Login',
component: Login
},
{
path: '/UserCenter',
name: 'UserCenter',
// component: UserCenter
component: () => import(/* webpackChunkName: "about" */ '../views/UserCenter.vue')
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
// 导航守卫
// 使用router.beforeEach注册一个全局前置守卫,判断用户是否登录
router.beforeEach((to, from, next) => {
// to到哪儿 from从哪儿离开 next跳转 为空就是放行
if (to.path === '/' || to.path === '/Login') {
next()
} else {
const token = localStorage.getItem('Authentication')
if (token == null || token === '') {
console.log('请先登录')
next({ name: 'Login' })
} else {
next()
}
}
})
export default router