go cas实现

这是之前实现的一个代码,觉得golang很有意思,虽然由于各种原因无法在工作中使用,但还是喜欢并去学习,思考怎么解决实际应用中的问题。工作中有使用过php CAS,然后根据php cas的ticket验证原理实现了一个go版本的,主要就是判断用户访问的URL中是否带ticket,如果否就直接重定向到CAS认证中心进行登录;如果带有ticket,也要到CAS认证中心去认证ticket的有效性,如果有效,则可以正常访问当前网页,否则重定向到认证中心的登录页面。以下为实现代码:

package cas

import (
    "io/ioutil"
    "net/http"
    "strings"
)

/*
判断当前访问是否已认证
 */
func IsAuthentication(w http.ResponseWriter, r *http.Request, casServerUrl string) bool {
    if !hasTicket(r) {
        redirectToCasServer(w, r, casServerUrl)
        return false
    }

    localUrl := getLocalUrl(r)
    if !validateTicket(localUrl, casServerUrl) {
        redirectToCasServer(w, r, casServerUrl)
        return false
    }
    return true
}

/*
重定向到CAS认证中心
 */
func redirectToCasServer(w http.ResponseWriter, r *http.Request, casServerUrl string) {
    casServerUrl = casServerUrl + "/login?service=" + getLocalUrl(r)
    http.Redirect(w, r, casServerUrl, http.StatusFound)
}

/*
验证访问路径中的ticket是否有效
 */
func validateTicket(localUrl, casServerUrl string) bool {
    casServerUrl = casServerUrl + "/serviceValidate?service=" + localUrl
    res, err := http.Get(casServerUrl)
    if err != nil {
        return false
    }
    defer res.Body.Close()

    data, err := ioutil.ReadAll(res.Body)
    if err != nil {
        return false
    }

    dataStr := string(data)
    if !strings.Contains(dataStr, "cas:authenticationSuccess") {
        return false
    }
    return true
}

/*
从请求中获取访问路径
 */
func getLocalUrl(r *http.Request) string {
    scheme := "http://"
    if r.TLS != nil {
        scheme = "https://"
    }
    url := strings.Join([]string{scheme, r.Host, r.RequestURI}, "")
    slice := strings.Split(url, "?")
    if len(slice) > 1 {
        localUrl := slice[0]
        urlParamStr := ensureOneTicketParam(slice[1])
        url = localUrl + "?" + urlParamStr
    }
    return url
}

/*
处理并确保路径中只有一个ticket参数
 */
func ensureOneTicketParam(urlParams string) string {
    if len(urlParams) == 0 || !strings.Contains(urlParams, "ticket") {
        return urlParams
    }

    sep := "&"
    params := strings.Split(urlParams, sep)

    newParams := ""
    ticket := ""
    for _, value := range params {
        if strings.Contains(value, "ticket") {
            ticket = value
            continue
        }

        if len(newParams) == 0 {
            newParams = value
        } else {
            newParams = newParams + sep + value
        }

    }
    newParams = newParams + sep + ticket
    return newParams
}

/*
获取ticket
 */
func getTicket(r *http.Request) string {
    return r.FormValue("ticket")
}

/*
判断是否有ticket
 */
func hasTicket(r *http.Request) bool {
    t := getTicket(r)
    return len(t) != 0
}

对于每个用户请求,直接调用IsAuthentication即可。

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页