package app
import (
_"github.com/go-sql-driver/mysql"
"github.com/go-xorm/xorm"
"github.com/labstack/echo/middleware"
"github.com/labstack/echo"
"github.com/dgrijalva/jwt-go"
"encoding/base64"
"math/rand"
"net/mail"
"net/smtp"
"os/exec"
"strings"
"time"
"log"
"fmt"
)
func main() { app.Run("localhost:3000") }
/*
项目依赖
github.com/go-sql-driver/mysql
github.com/go-xorm/xorm
github.com/dgrijalva/jwt-go
github.com/labstack/echo
*/
/*
静态服务器 路由处理器 路由组 (子域)
======================================== 中间件
请求记录 Logger
程序恢复 Recover
安全保护 Secure
防止攻击 CSRF
请求跨域 CORS
访问认证 JWT
======================================== HTTP 请求 Request
ctx.Bind() // 读取 FORM && JSON
ctx.Param() // 读取动态路由/:id
ctx.FormValue() // 读取单个表单值
ctx.FormFile() // 读取文件
ctx.FormParams() //
======================================== HTTP 响应 Response
ctx.String() // 发送 字符串
ctx.HTML() // 发送 HTML
ctx.JSON() // 发送 JSON
ctx.JSONP() // 发送
ctx.JSONPretty() // 发送 JSON带缩进
ctx.JSONBlob() // 发送
ctx.JSONPBlob() // 发送
ctx.XML() // 发送 XML
ctx.XMLPretty() // 发送 XML带缩进
ctx.XMLBlob() // 发送
ctx.File() // 发送 文件
ctx.Attachment() // 发送 文件附件
ctx.Inline() // 发送 内联
ctx.Blob() // 发送
ctx.Stream() // 发送 数据流
ctx.NoContent() // 发送 带有状态码的空白体
ctx.Redirect() // 请求重定向
========================================
*/
var db *xorm.Engine
func init() {
var err error
if db, err = xorm.NewEngine("mysql", "root:123456@/mydb?charset=utf8"); err != nil {
log.Println(err)
}
// 数据表同步
if err = db.Sync2();
err != nil {
log.Println(err)
}
}
// 入口
func Run(un string) {
e := echo.New()
e.Use(LOGGER, CORS)
e.Static("/", "./assets")
e.Static("/dist", "./assets/dist")
e.File("/", "./assets/dist/index.html")
e.File("*", "./assets/dist/index.html")
e.Logger.Fatal(e.Start(un))
}
// 读取用户提交
func ReadForm(ctx echo.Context, m interface{}) error {
if err := ctx.Bind(m); err != nil {
return ctx.JSON(500, "服务器不支持提交类型")
}
return nil
}
// JWT分发器
func SendJWT(data interface{}) string {
// "Authorization":"Bearer " + JSON.parse(localStorage.getItem("token"))
// 创建一个新的令牌对象
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"user": data,
"iat": time.Now().Unix(), // 发布时间
"nbf": time.Now().Unix(), // 有效起始时间
"exp": time.Now().Add(time.Hour * 2).Unix(), // 过期时间(2小时)
"iss": nil, // 发行者
"sub": nil, // 标题
"aud": nil, // 客户(多发行者时使用)
"jti": nil, // 唯一标识
})
// 设置令牌签名
tokenString, err := token.SignedString([]byte("xxx"))
if err != nil {
panic(err)
}
return tokenString
}
// 随机字符种子
func RandomChar(l int) string {
str := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
strs := []byte(str)
result := []byte{}
r := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < l; i++ {
result = append(result, strs[r.Intn(len(strs))])
}
return string(result)
}
var (
/*JWT认证*/ JwtServe = middleware.JWTWithConfig(middleware.JWTConfig{
SigningKey: []byte("xxx"),
})
/*请求记录*/ LOGGER = middleware.LoggerWithConfig(middleware.LoggerConfig{Format: "${time_rfc3339} [${status}] ${method} ${uri}\n"})
/*请求跨域*/ CORS = middleware.CORSWithConfig(middleware.CORSConfig{})
/*程序恢复*/ Recover = middleware.RecoverWithConfig(middleware.RecoverConfig{})
/*安全保护*/ Secure = middleware.SecureWithConfig(middleware.SecureConfig{})
/*防止攻击*/ CSRF = middleware.CSRFWithConfig(middleware.CSRFConfig{})
)
// ===============================================
// 邮件分发器
var EmailServe = New(Config{
Host: "smtp.sina.com",
Username: "upcyan@sina.com",
Password: "1718408254",
Port: 25,
})
type (
// 发件人邮箱配置
Config struct {
Host string // 邮箱服务器主机
Port int // 监听端口
Username string // 发件人的帐号
Password string // 发件人的密码
FromAddr string // 邮件头的'from'部分,它覆盖用户名
FromAlias string // 如果是空的,这是@用户名字段之前的第一部分
UseCommand bool // 如果要使用mail命令发送电子邮件而不是smtp,则使用命令启用它
// 主机,端口和密码将被忽略 仅适用于UNIX
}
Service interface {
Send(string, string, ...string) error
}
mailer struct {
config Config
fromAddr mail.Address
auth smtp.Auth
authenticated bool
}
)
// 创建并返回新的邮件服务
func New(cfg Config) Service {
m := &mailer{config: cfg}
addr := cfg.FromAddr
if addr == "" {
addr = cfg.Username
}
if cfg.FromAlias == "" {
if !cfg.UseCommand && cfg.Username != "" && strings.Contains(cfg.Username, "@") {
m.fromAddr = mail.Address{Name: cfg.Username[0:strings.IndexByte(cfg.Username, '@')], Address: addr}
}
} else {
m.fromAddr = mail.Address{Name: cfg.FromAlias, Address: addr}
}
return m
}
func (m *mailer) Send(subject string, body string, to ...string) error {
if m.config.UseCommand {
return m.sendCmd(subject, body, to)
}
return m.sendSMTP(subject, body, to)
}
func (m *mailer) sendSMTP(subject string, body string, to []string) error {
if !m.authenticated {
cfg := m.config
if cfg.Username == "" || cfg.Password == "" || cfg.Host == "" || cfg.Port <= 0 {
return fmt.Errorf("Username, Password, Host & Port cannot be empty when using SMTP!")
}
m.auth = smtp.PlainAuth("", cfg.Username, cfg.Password, cfg.Host)
m.authenticated = true
}
fullhost := fmt.Sprintf("%s:%d", m.config.Host, m.config.Port)
header := make(map[string]string)
header["From"] = m.fromAddr.String()
header["To"] = strings.Join(to, ",")
header["Subject"] = subject
header["Content-Type"] = "text/html; charset=\"utf-8\""
header["Content-Transfer-Encoding"] = "base64"
message := ""
for k, v := range header {
message += fmt.Sprintf("%s: %s\r\n", k, v)
}
message += "\r\n" + base64.StdEncoding.EncodeToString([]byte(body))
return smtp.SendMail(
fmt.Sprintf(fullhost),
m.auth,
m.config.Username,
to,
[]byte(message),
)
}
func (m *mailer) sendCmd(subject string, body string, to []string) error {
header := make(map[string]string)
header["To"] = strings.Join(to, ",")
header["Subject"] = subject
header["Content-Type"] = "text/html; charset=\"utf-8\""
header["Content-Transfer-Encoding"] = "base64"
message := ""
for k, v := range header {
message += fmt.Sprintf("%s: %s\r\n", k, v)
}
message += "\r\n" + base64.StdEncoding.EncodeToString([]byte(body))
cmd := exec.Command("sendmail", "-F", m.fromAddr.Name, "-f", m.fromAddr.Address, "-t")
_, err := cmd.CombinedOutput()
return err
}
转载于:https://my.oschina.net/upcyan/blog/1359448