大型网站平台建设,抖音代运营怎么跟客户沟通并成交,加强网站技术建设,重庆智慧团建网站登录平台本篇使用Vue2开发前端#xff0c;Go语言开发服务端#xff0c;使用nginx代理部署实现登录页面及其校验功能。
目录
1.部署结构
2.Vue2前端
2.1代码结构
2.1源码
3.Go后台服务
3.2代码结构
3.2 源码
3.3单测效果
4.nginx
5.运行效果
6.问题总结 1.部署结构 2.Vue2… 本篇使用Vue2开发前端Go语言开发服务端使用nginx代理部署实现登录页面及其校验功能。
目录
1.部署结构
2.Vue2前端
2.1代码结构
2.1源码
3.Go后台服务
3.2代码结构
3.2 源码
3.3单测效果
4.nginx
5.运行效果
6.问题总结 1.部署结构 2.Vue2前端
2.1代码结构 2.1源码
index.html !DOCTYPE html html head meta charsetutf-8 meta nameviewport contentwidthdevice-width,initial-scale1.0 titledemo/title /head body div idmyapp/div !-- built files will be auto injected -- /body /html src/App.vue template div router-view/router-view /div /template src/assets/css/reset.css /* http://meyerweb.com/eric/tools/css/reset/ v2.0 | 20110126 License: none (public domain) */ html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; } /* HTML5 display-role reset for older browsers */ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; } body { line-height: 1; } ol, ul { list-style: none; } blockquote, q { quotes: none; } blockquote:before, blockquote:after, q:before, q:after { content: ; content: none; } table { border-collapse: collapse; border-spacing: 0; } src/components/Home.vue template div idYYYYYYYYYYY classhello button clickgoLogin登录/button el-button typeprimary你好/el-button el-button typeinfo你好/el-button el-button typedanger你好/el-button el-button typesuccess你好/el-button el-tag fsfsd dsd dsfv/el-tag i classfa fa-user/i i classfa fa-users/i /div /template style langscss .hello { background: yello; .el-button { color: red; } } import url(../assets/css/reset.css) /style script export default { methods: { goLogin () { this.$router.push(/login) } } } /script src/components/Login.vue template div classlogin el-card classbox-card div slotheader classclearfix span业务后台管理系统/span /div el-form label-width100px :modelform refform :rulesrules el-form-item label用户名 propusername el-input v-modelform.username/el-input /el-form-item el-form-item label密码 proppassword el-input typepassword v-modelform.password/el-input /el-form-item el-form-item el-button typeprimary clicklogin(form)登录/el-button /el-form-item /el-form /el-card /div /template /* 原生AJAX和Axios在使用上存在一定的区别。Axios可以支持多种方式包括浏览器环境、node环境而AJAX则只能在浏览器环境中使用。 Axios还支持多种请求方式,包括GET、POST、PUT、DELETE等而AJAX只能支持GET和POST方式发送请求。此外Axios还可以拦截请求和响应。 */ script //登录验证的封装 import {nameRule, passRule} from ../utils/validate.js import {setToken} from /utils/dealtoken.js export default { data () { return { form: { username: , password: }, rules: { username: [{validator: nameRule, required: true, trigger: blur}], password: [{validator: passRule, required: true, trigger: blur}] } } }, methods: { login(form) { this.$refs[form].validate((valid) { if (valid) { console.log(this.form) //this.$router.push(/home) //解决axios post请求 404 OPTIONS问题 const posthead { headers: { Content-Type: text/plain;charsetutf-8, }, //withCredentials: same-origin } this.axios.post(http://localhost:8282/login, JSON.stringify(this.form), posthead).then(res { console.log(res) if (res.status 200) { //localStorage.setItem(username, res.data.username) setToken(username, res.data.username) this.$message({message: res.data, type: success}) this.$router.push(/home) console.log(post mid) } }) } else { console.error(this.form) } }) } } } /script style langscss .login { width: 100%; height: 100%; position: absolute; background: #409EFF; .box-card { width: 450px; margin: 200px auto; .el-card_header { font-size: 34px; } .el-button { width: 100%; } } } /style src/main.js import Vue from vue import App from ./App import font-awesome/css/font-awesome.min.css import axios from axios import router from ./router // 挂载到原型就可以全局使用 Vue.prototype.axios axios import ElementUI from element-ui import element-ui/lib/theme-chalk/index.css Vue.use(ElementUI) new Vue({ router, render: h h(App) }).$mount(#myapp) src/router/index.js import Vue from vue import Home from /components/Home import VueRouter from vue-router Vue.use(VueRouter) const routes [ { path: /, redirect: /login, component: () import(/components/Login) }, { path: /login, name: Login, component: () import(/components/Login) }, { path: /home, component: Home }, { path: *, component: Home } ] export default new VueRouter({ mode: history, routes: routes }) src/utils/validate.js // Token的封装 Token存放在localStorage export function setToken(tokenkey, token) { return localStorage.setItem(tokenkey, token) } export function getToken(tokenkey) { return localStorage.getItem(tokenkey) } export function removeToken(tokenkey) { return localStorage.removeItem(tokenkey) } src/utils/dealtoken.js //用户名匹配 export function nameRule (rule, value, callback) { let reg /(^[a-zA-Z0-9]{4,10}$)/; if (value ) { callback(new Error(请输入用户名)); } else if (!reg.test(value)) { callback(new Error(请输入4-10用户名)); } else { callback(); } } //密码匹配 export function passRule (rule, value, callback) { let pass /^\S*(?\S{6,12})(?\S*\d)(?\S*[A-Z])(?\S*[a-z])(?\S*[!#$%^*? ])\S*$/; if (value ) { callback(new Error(请输入密码)); } else if (!pass.test(value)) { callback(new Error(请输入6-12位密码需要包含大小写和数字及特殊字符)); } else { callback(); } } plugins/element.js import Vue from vue import { Button, Tag } from element-ui Vue.use(Button) Vue.use(Tag) 3.Go后台服务
3.2代码结构 3.2 源码
controller/login.go package controller import ( encoding/json fmt io/ioutil net/http path/filepath github.com/gin-gonic/gin ) // post http://127.0.0.1:8181/login // axios.post 和 post json处理 func LoginPost(ctx *gin.Context) { version : ctx.DefaultQuery(version, V1.0.0.1) //前端使用axios直接传递form时,axios会默认使用json,必须使用下面方式获取json数据,解析后再使用 data, _ : ioutil.ReadAll(ctx.Request.Body) type UserInfo struct { Username string Password string } var u UserInfo err : json.Unmarshal(data, u) if err ! nil { fmt.Println(err) } username : u.Username password : u.Password fmt.Println(login info:: , version, username, password) /* ctx.Header(Access-Control-Allow-Origin, *) ctx.Header(Access-Control-Allow-Headers, Content-Type,AccessToken,X-CSRF-Token, Authorization, Token) ctx.Header(Access-Control-Allow-Credentials, true) ctx.Header(Access-Control-Allow-Methods, POST, GET, OPTIONS, PUT, DELETE) ctx.Header(content-type, application/json;charsetUTF-8) ctx.Writer.Header().Set(Access-Control-Max-Age, 86400) ctx.Writer.Header().Set(Access-Control-Allow-Methods, *) ctx.Writer.Header().Set(Access-Control-Allow-Headers, *) ctx.Writer.Header().Set(Access-Control-Expose-Headers, *) ctx.Writer.Header().Set(Access-Control-Allow-Credentials, true) */ if username 123456 password 1234abcdE { ctx.String(http.StatusOK, 登录成功) } else { ctx.String(http.StatusNotFound, 用户名或密码错误) } } // http://127.0.0.1:8181/formlogin // form表单提交处理 application/x-www-form-urlencoded func FormLoginPost(ctx *gin.Context) { //第一种 username : ctx.PostForm(username) password : ctx.PostForm(password) //第二种 /* username : ctx.DefaultPostForm(username, somebody) password : ctx.DefaultPostForm(password, ***) */ //第三种 /* username, ok : ctx.GetPostForm(username) if !ok { username 取不到的话 } password, ok : ctx.GetPostForm(password) if !ok { password *** } */ fmt.Println(FormLoginPost :: , username, password) /* ctx.HTML(http.StatusOK, home.html, gin.H{ Name: username, Password: password, }) */ ctx.JSON(http.StatusOK, gin.H{ Name: username, Password: password, }) if username 123456 password 1234abcdE { ctx.String(http.StatusOK, 登录成功) } else { ctx.String(http.StatusNotFound, 用户名或密码错误) } } // form表单提交文件上传处理 multipart/form-data func UploadFile(ctx *gin.Context) { file, _ : ctx.FormFile(uploadfile) fmt.Println(file.Filename) file_path : upload/ filepath.Base(file.Filename) fmt.Println(file_path) ctx.SaveUploadedFile(file, file_path) ctx.String(http.StatusOK, 上传成功) } server.go package main import ( main/controller net/http github.com/gin-contrib/cors github.com/gin-gonic/gin ) /* // 错误 server.go:4:2: package main/controller is not in GOROOT (/home/tiger/go/go/src/main/controller) go mod init main //错误 server.go:7:2: no required module provides package github.com/gin-gonic/gin; to add it: go get github.com/gin-gonic/gin //处理跨域框架 go get github.com/gin-contrib/cors */ /* 当客户端尤其是基于 Web 的客户端想要访问 API 时服务器会决定允许哪些客户端发送请求。这是通过使用称为 CORS 来完成的它代表跨源资源共享。 跨域资源共享 CORS 是一种机制允许从提供第一个资源的域之外的另一个域请求网页上的受限资源。 */ func CrosHandler() gin.HandlerFunc { return func(context *gin.Context) { context.Writer.Header().Set(Access-Control-Allow-Origin, *) context.Header(Access-Control-Allow-Origin, *) // 设置允许访问所有域 context.Header(Access-Control-Allow-Methods, POST,GET,OPTIONS,PUT,DELETE,UPDATE) context.Header(Access-Control-Allow-Headers, Authorization, Content-Length, X-CSRF-Token, Token,session,X_Requested_With,Accept, Origin, Host, Connection, Accept-Encoding, Accept-Language,DNT, X-CustomHeader, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, Pragma,token,openid,opentoken) context.Header(Access-Control-Expose-Headers, Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers,Cache-Control,Content-Language,Content-Type,Expires,Last-Modified,Pragma,FooBar) context.Header(Access-Control-Max-Age, 172800) context.Header(Access-Control-Allow-Credentials, true) context.Set(content-type, application/json) //设置返回格式是json //处理请求 context.Next() } } // http://127.0.0.1:8181/ping // http://127.0.0.1:8181/index func main() { r : gin.Default() // 设置全局跨域访问 //r.Use(CrosHandler()) //cors处理跨域 r.Use(cors.Default()) // 返回一个json数据 r.GET(/ping, func(c *gin.Context) { c.JSON(200, gin.H{ message: pong, num: 888, }) }) // 返回一个html页面 r.LoadHTMLGlob(templates/*) r.GET(/index, func(c *gin.Context) { c.HTML(http.StatusOK, index.html, nil) }) r.POST(/login, controller.LoginPost) r.POST(/formlogin, controller.FormLoginPost) r.POST(/upload, controller.UploadFile) //r.Run() // r.Run(:8080) 监听并在 0.0.0.0:8080 上启动服务 r.Run(:8181) } templates/home.html 欢迎进入首页 templates/index.html !DOCTYPE html html langen head meta charsetUTF-8/ title欢迎进入首页/title /head body h3登录测试/h3 hr/ form actionhttp://localhost:8282/formlogin methodpost table border0 title测试 tr td用户名/td tdinput typetext nameusername/td /tr tr td密码/td tdinput typepassword namepassword/td /tr tr td colspan2 input typereset / input typesubmit value登录 / /td /tr /table /form br h3文件上传测试/h3 hr/ form actionhttp://localhost:8282/upload methodpost enctypemultipart/form-data input typefile nameuploadfile/ input typesubmit valueupload /form /body /html 3.3单测效果
http://127.0.0.1:8181/ping http://127.0.0.1:8181/index 上传文件 8282端口nginx代理测试 4.nginx #user nobody; worker_processes 1; #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #pid logs/nginx.pid; events { worker_connections 1024; } #location [ | ~ | ~* | ^~ ] uri { } # ~区分大小写的正则匹配 # ~*不区分大小写的正则匹配 # ^~常规字符串匹配 http { include mime.types; default_type application/octet-stream; #log_format main $remote_addr - $remote_user [$time_local] $request # $status $body_bytes_sent $http_referer # $http_user_agent $http_x_forwarded_for; #access_log logs/access.log main; sendfile on; #tcp_nopush on; #keepalive_timeout 0; keepalive_timeout 65; fastcgi_intercept_errors on; #gzip on; limit_conn_zone $binary_remote_addr zoneaddr:10m; #代理静态页面 server { listen 80; server_name www.liudehua.com; #charset koi8-r; #access_log logs/host.access.log main; location / { root /home/tiger/nginx-1.22.1/nginx/html/dist; index index.html; try_files $uri $uri/ /index.html; } #404配置 #error_page 404 /404.html; #location /404.html { # alias /home/tiger/nginx-1.22.1/nginx/html/dist; # index index.html index.htm; #} #error_page 404 /404.html; # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location /50x.html { root html; } # proxy the PHP scripts to Apache listening on 127.0.0.1:80 # #location ~ \.php$ { # proxy_pass http://127.0.0.1; #} # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # #location ~ \.php$ { # root html; # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include fastcgi_params; #} # deny access to .htaccess files, if Apaches document root # concurs with nginxs one # #location ~ /\.ht { # deny all; #} } #代理真正的后台服务 server { listen 8282; location / { proxy_pass http://127.0.0.1:8181/; } } # another virtual host using mix of IP-, name-, and port-based configuration # #server { # listen 8000; # listen somename:8080; # server_name somename alias another.alias; # location / { # root html; # index index.html index.htm; # } #} # HTTPS server # #server { # listen 443 ssl; # server_name localhost; # ssl_certificate cert.pem; # ssl_certificate_key cert.key; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 5m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # location / { # root html; # index index.html index.htm; # } #} } 部署前端程序: 启动nginx 5.运行效果
http://www.liudehua.com/ 可以看到nginx反向代理 postman测试
不代理测试8181端口 代理测试8282端口 6.问题总结
6.1 跨域访问错误前后台一块解决 6.2 form表单请求axios.post请求Go解析处理 6.2 vue中的正则表达式 vscode安装插件any-rule插件 ctrl shift p 输入密码选择正则表达式