网站怎么做移动端的,徐州双语网站制作,泰安达创信息科技有限公司,网站建设网站系统选择1. 环境准备2. 创建项目3. Vue配置步骤一: 安装包步骤二: 配置文件步骤三: 页面文件 4. 后台配置 在本教程中#xff0c;我将利用Visual Studio 2022的强大集成开发环境#xff0c;结合Vue.js前端框架和ASP.NET Core后端框架#xff0c;从头开始创建一个具备用户登录与权限验… 1. 环境准备2. 创建项目3. Vue配置步骤一: 安装包步骤二: 配置文件步骤三: 页面文件 4. 后台配置 在本教程中我将利用Visual Studio 2022的强大集成开发环境结合Vue.js前端框架和ASP.NET Core后端框架从头开始创建一个具备用户登录与权限验证功能的Web应用程序。我们将充分利用Visual Studio的内置工具和模板来简化开发流程。 1. 环境准备
Visual Studio 2022,Vue3
2. 创建项目
打开Visual Studio 2022选择“创建新项目”。在项目模板搜索框中输入“Vue and ASP.NET Core”选择模板后点击“下一步”。 按照图中配置: 生成目录如下:
3. Vue配置
步骤一: 安装包
右键npm-安装新的npm包
element-plus UI包element-plus/icons-vue UI图标包axios 发送请求的包qs 发送请求时序列化的包vue-router vue路由jwt-decode 令牌解码
步骤二: 配置文件 封装axios 新建axios.js文件,内容如下: // axios.jsimport axios from axios;
import PLATFROM_CONFIG from ../public/config;const instance axios.create({baseURL: PLATFROM_CONFIG.baseURL, // 替换为实际的 API 地址timeout: 10000,
});instance.defaults.headers.post[Content-Type] application/json;// 添加请求拦截器
axios.interceptors.request.use((config) {// 在发送请求之前做些什么return config;
}, function (error) {// 对请求错误做些什么return Promise.reject(error);
});// 添加响应拦截器
axios.interceptors.response.use(function (response) {// 对响应数据做点什么if (response.status 200) {return Promise.resolve(response);} else {return Promise.reject(response);}
}, function (error) {// 对响应错误做点什么return Promise.reject(error);
});export const get (url, params) {return instance.get(url, { params });
};export const post (url, data) {// data QS.stringify(data);return instance.post(url, data);
}; 创建路由 新建router文件夹,并新建router.js文件
import { createRouter, createWebHashHistory } from vue-routerimport qs from qs;
import { ElMessage } from element-plusimport { post } from ../axios;import Home from ../components/Home.vue
import Setting from ../components/Setting.vue
import Login from ../components/Login.vue
import LoginOut from ../components/LoginOut.vue// 路由配置
const routes [{ path: /, component: Home },{ path: /Login, component: Login },{ path: /Setting, component: Setting, meta: { requiresAuth: true, role: ShortcutManage; } },{ path: /LoginOut, component: LoginOut },
]const router createRouter({history: createWebHashHistory(),routes,
})
// 路由守卫,在这里创建验证的流程
router.beforeEach((to, from, next) {const accessToken localStorage.getItem(accessToken);if (to.meta.requiresAuth !accessToken) {// 如果需要认证并且没有令牌则重定向到登录页next(/Login);} else {if (to.meta.requiresAuth) {// 如果有令牌判断令牌是否过期//判断令牌是否过期const decodedToken jwtDecode(accessToken);const expirationTime decodedToken.exp * 1000;const isTokenExpired expirationTime Date.now();// 已经过期if (isTokenExpired) {next(/LoginOut);} else { // 没有过期// 判断是否需要指定权限if (typeof (to.meta.role) ! undefined to.meta.role ! null) {let USER_INFO qs.parse(localStorage.getItem(userInfo))post(Login/ValidPerm, { username: USER_INFO.ad, userPowr: to.meta.role }).then(res {next();}).catch(err {console.log(err)ElMessage({message: 您没有权限,请联系管理员!,type: warning,})})} else {next();}}} else {next();}}
});export default router配置main.js
import ./assets/main.cssimport { createApp } from vue
import ElementPlus from element-plus
import { ElMessage} from element-plus
import element-plus/dist/index.css
import router from ./router/router
import * as ElementPlusIconsVue from element-plus/icons-vue
import { get, post } from ./axios;
import App from ./App.vue
import * as utils from ./utils;
import qs from qsimport ELHeader from ./components/custom/ElHeader.vue
import ElAside from ./components/custom/ElAside.vueconst app createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {app.component(key, component)
}Object.entries(utils).forEach(([key, value]) {app.config.globalProperties[$${key}] value;
});app.config.globalProperties.$get get;
app.config.globalProperties.$qs qs;
app.config.globalProperties.$post post;
app.config.globalProperties.$message ElMessage;app.config.globalProperties.$USER_INFO qs.parse(localStorage.getItem(userInfo))app.use(ElementPlus)
app.use(router)app.component(ELHeader, ELHeader).component(ELAside,ElAside); app.mount(#app)步骤三: 页面文件
登陆页面Login.vue
templateel-form :modelloginForm refloginForm :inlinefalse sizelargeel-form-item propUsername :rules{required: true,message: Username can not be null,trigger: blur,
}el-input v-modelloginForm.Username placeholderOkta Accounttemplate #prependel-iconUser //el-icon/template/el-input/el-form-itemel-form-item propPassword :rules{required: true,message: Password can not be null,trigger: blur,
}el-input typepassword v-modelloginForm.Password placeholderOkta Passwordtemplate #prependel-iconLock //el-icon/template/el-input/el-form-itemel-form-itemel-button classlogin-btn typeprimary clickloginOn登陆/el-button/el-form-item/el-form
/template
script langjs
import { defineComponent } from vue;
export default defineComponent({data() {return {loginForm: {Username: ,Password: ,auth: ShortcutLinks}}},methods: {loginOn() {this.$refs.loginForm.validate((valid) {if (valid) {let that thisthis.$post(/Login/LoginVerify, this.loginForm).then(res {if (res.data.success) {// 检测是否有TokenlocalStorage.setItem(accessToken, res.data.data.token)let userInfo res.data.datauserInfo.token nulllocalStorage.setItem(userInfo, this.$qs.stringify(userInfo))that.$router.push(/)} else {this.$message({showClose: true,message: res.data.message,type: warning,})}}).catch(err {console.error(err)})} else {console.log(error submit!)return false}})}},mounted(){this.Yaer new Date().getFullYear()}
})
/script注销界面LoginOut.vue
templatediv退出登陆成功!/div
/templatescript langjs
import { defineComponent } from vue;export default defineComponent({data() {return {}}, mounted() {localStorage.removeItem(userInfo);localStorage.removeItem(accessToken); this.$router.push(/Login);}
})
/script修改App.vue templaterouter-view/router-view
/templatestyle scoped/style
4. 后台配置
创建一个生成Token的工具类TokenService public class TokenService{private readonly string _secretKey;private readonly string _issuer;private readonly string _audience;public TokenService(string secretKey, string issuer, string audience){_secretKey secretKey;_issuer issuer;_audience audience;}public string GenerateToken(string username){var securityKey new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_secretKey));var credentials new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);var claims new[]{new Claim(ClaimTypes.Name, username),// Add additional claims as needed};var token new JwtSecurityToken(_issuer,_audience,claims,expires: DateTime.Now.AddMonths(1), // Token expiration timesigningCredentials: credentials);return new JwtSecurityTokenHandler().WriteToken(token);}}配置跨域Program.cs 在Buidl()之前增加:
var MyAllowSpecificOrigins _myAllowSpecificOrigins;builder.Services.AddCors(options
{options.AddPolicy(name: MyAllowSpecificOrigins, policy {policy.WithOrigins(*).AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();});
});登陆验证 LoginController.cs [HttpPost(LoginVerify)]public async TaskResultLoginInfo LoginVerify([FromBody] LoginModel loginModel){if (string.IsNullOrEmpty(loginModel.Username) || string.IsNullOrEmpty(loginModel.Password)){return ResultLoginInfo.Fail(用户名或密码不能为空!);}if (string.IsNullOrEmpty(loginModel.Auth) || !ShortcutLinks.Equals(loginModel.Auth)){return ResultLoginInfo.Fail(令牌识别错误!);}string responseContent await IsValidUser(loginModel.Username, loginModel.Password);if (Unauthorized.Equals(responseContent)){return ResultLoginInfo.Fail(验证失败!);}if (The user name or password is incorrect..Equals(responseContent)){return ResultLoginInfo.Fail(用户名或密码错误!);}try{// 加密秘钥,可以自定义string key Ns9XoAdW7Pb3Cv9Fm2Zq4t6w8y/B?E(HMbQeThWmZq4t7w9z$CF)JNcRfUjXn2r5u8x/A%D*G-KaPdSgVkYp3s6v9y;// 我自己的登陆验证方法,根据实际情况可以修改LoginInfo loginInfo JsonConvert.DeserializeObjectLoginInfo(responseContent);// 生成验证的Tokenvar tokenService new TokenService(key, ShortcutLinksServer, ShortcutLinksClient);// 为Token添加一个标识,我这里使用的用户的ADvar token tokenService.GenerateToken(loginInfo.AD);loginInfo.token token;// 生成的信息返回前天return ResultLoginInfo.Suc(loginInfo);}catch (Exception){return ResultLoginInfo.Fail(登陆失败!);}}