userauth_radius.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. package dbdata
  2. import (
  3. "context"
  4. "encoding/json"
  5. "errors"
  6. "fmt"
  7. "reflect"
  8. "time"
  9. "layeh.com/radius"
  10. "layeh.com/radius/rfc2865"
  11. )
  12. type AuthRadius struct {
  13. Addr string `json:"addr"`
  14. Secret string `json:"secret"`
  15. }
  16. func init() {
  17. authRegistry["radius"] = reflect.TypeOf(AuthRadius{})
  18. }
  19. func (auth AuthRadius) checkData(authData map[string]interface{}) error {
  20. authType := authData["type"].(string)
  21. bodyBytes, err := json.Marshal(authData[authType])
  22. if err != nil {
  23. return errors.New("Radius的密钥/服务器地址填写有误")
  24. }
  25. json.Unmarshal(bodyBytes, &auth)
  26. if !ValidateIpPort(auth.Addr) {
  27. return errors.New("Radius的服务器地址填写有误")
  28. }
  29. // freeradius官网最大8000字符, 这里限制200
  30. if len(auth.Secret) < 8 || len(auth.Secret) > 200 {
  31. return errors.New("Radius的密钥长度需在8~200个字符之间")
  32. }
  33. return nil
  34. }
  35. func (auth AuthRadius) checkUser(name, pwd string, g *Group) error {
  36. pl := len(pwd)
  37. if name == "" || pl < 1 {
  38. return fmt.Errorf("%s %s", name, "密码错误")
  39. }
  40. authType := g.Auth["type"].(string)
  41. if _, ok := g.Auth[authType]; !ok {
  42. return fmt.Errorf("%s %s", name, "Radius的radius值不存在")
  43. }
  44. bodyBytes, err := json.Marshal(g.Auth[authType])
  45. if err != nil {
  46. return fmt.Errorf("%s %s", name, "Radius Marshal出现错误")
  47. }
  48. err = json.Unmarshal(bodyBytes, &auth)
  49. if err != nil {
  50. return fmt.Errorf("%s %s", name, "Radius Unmarshal出现错误")
  51. }
  52. // radius认证时,设置超时3秒
  53. packet := radius.New(radius.CodeAccessRequest, []byte(auth.Secret))
  54. rfc2865.UserName_SetString(packet, name)
  55. rfc2865.UserPassword_SetString(packet, pwd)
  56. ctx, done := context.WithTimeout(context.Background(), 3*time.Second)
  57. defer done()
  58. response, err := radius.Exchange(ctx, packet, auth.Addr)
  59. if err != nil {
  60. return fmt.Errorf("%s %s", name, "Radius服务器连接异常, 请检测服务器和端口")
  61. }
  62. if response.Code != radius.CodeAccessAccept {
  63. return fmt.Errorf("%s %s", name, "Radius:用户名或密码错误")
  64. }
  65. return nil
  66. }