HydroCMS完成Ip地址段的权限设计

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hotqin888/article/details/51472738

 1、权限改成2种,第一种是写权限,由登录session进行判断权限;第二种是访问权限,登录或IP地址段权限,比如,不想登录,则根据预先设定的IP地址段如下 58.96.172.1 58.96.172.255 2——ip地址段(地址范围,权限) 58.96.173.1 58.96.172.255 3 58.96.172.22 1——指定单独ip的权限 进行判断来者的ip以及对应的权限。 如此,局域网中的用户可无障碍进行互访对方的cms了。 2、页面刷新后回到之前的位置。一般情况下,页面刷新后回到顶端,如何保证回到原来的定位?通过一段js代码就可以在cookie中记住竖向滚动条的位置,刷新后再回到那个位置。用户体验更好。 3、完成了在线计划表格的修改增加删除。这样,图纸目录就可以在线修改了。 4、分页中,在后几页中删除结果后刷新页面,就回到第一页,修改了这个bug。

下一步是目录的访问权限任意设置。

// 1 init函数是用于程序执行前做包的初始化的函数,比如初始化包里的变量等
// 2 每个包可以拥有多个init函数
// 3 包的每个源文件也可以拥有多个init函数
// 4 同一个包中多个init函数的执行顺序go语言没有明确的定义(说明)
// 5 不同包的init函数按照包导入的依赖关系决定该初始化函数的执行顺序
// 6 init函数不能被其他函数调用,而是在main函数执行之前,自动被调用
//读取iprole.txt文件,作为全局变量Iprolemaps,供调用访问者ip的权限用
var (
	Iprolemaps map[string]int
)
func init() {
	Iprolemaps = make(map[string]int)
	f, err := os.OpenFile("./conf/iprole.txt", os.O_RDONLY, 0660)
	if err != nil {
		fmt.Fprintf(os.Stderr, "%s err read from %s : %s\n", err)
	}
	var scanner *bufio.Scanner
	scanner = bufio.NewScanner(f)
	for scanner.Scan() {
		args := strings.Split(scanner.Text(), " ")
		maps := processFlag(args)
		for i, v := range maps {
			Iprolemaps[i] = v
		}
	}
	f.Close()
}
//取得访问者的权限
func Getiprole(ip string) (role int) {
	role = Iprolemaps[ip]
	return role
}

//获取下一个IP
func nextIp(ip string) string {
	ips := strings.Split(ip, ".")
	var i int
	for i = len(ips) - 1; i >= 0; i-- {
		n, _ := strconv.Atoi(ips[i])
		if n >= 255 {
			//进位
			ips[i] = "1"
		} else {
			//+1
			n++
			ips[i] = strconv.Itoa(n)
			break
		}
	}
	if i == -1 {
		//全部IP段都进行了进位,说明此IP本身已超出范围
		return ""
	}
	ip = ""
	leng := len(ips)
	for i := 0; i < leng; i++ {
		if i == leng-1 {
			ip += ips[i]
		} else {
			ip += ips[i] + "."
		}
	}
	return ip
}

//生成IP地址列表
func processIp(startIp, endIp string) []string {
	var ips = make([]string, 0)
	for ; startIp != endIp; startIp = nextIp(startIp) {
		if startIp != "" {
			ips = append(ips, startIp)
		}
	}
	ips = append(ips, startIp)
	return ips
}

func processFlag(arg []string) (maps map[string]int) {
	//开始IP,结束IP
	var startIp, endIp string
	//端口
	var ports []int = make([]int, 0)
	index := 0
	startIp = arg[index]
	si := net.ParseIP(startIp)
	if si == nil {
		//开始IP不合法
		fmt.Println("'startIp' Setting error")
		return nil
	}
	index++
	endIp = arg[index]
	ei := net.ParseIP(endIp)
	if ei == nil {
		//未指定结束IP,即只扫描一个IP
		endIp = startIp
	} else {
		index++
	}

	tmpPort := arg[index]
	if strings.Index(tmpPort, "-") != -1 {
		//连续端口
		tmpPorts := strings.Split(tmpPort, "-")
		var startPort, endPort int
		var err error
		startPort, err = strconv.Atoi(tmpPorts[0])
		if err != nil || startPort < 1 || startPort > 65535 {
			//开始端口不合法
			return nil
		}
		if len(tmpPorts) >= 2 {
			//指定结束端口
			endPort, err = strconv.Atoi(tmpPorts[1])
			if err != nil || endPort < 1 || endPort > 65535 || endPort < startPort {
				//结束端口不合法
				fmt.Println("'endPort' Setting error")
				return nil
			}
		} else {
			//未指定结束端口
			endPort = 65535
		}
		for i := 0; startPort+i <= endPort; i++ {
			ports = append(ports, startPort+i)
		}
	} else {
		//一个或多个端口
		ps := strings.Split(tmpPort, ",")
		for i := 0; i < len(ps); i++ {
			p, err := strconv.Atoi(ps[i])
			if err != nil {
				//端口不合法
				fmt.Println("'port' Setting error")
				return nil
			}
			ports = append(ports, p)
		}
	}

	//生成扫描地址列表
	ips := processIp(startIp, endIp)
	il := len(ips)
	m1 := make(map[string]int)
	for i := 0; i < il; i++ {
		pl := len(ports)
		for j := 0; j < pl; j++ {
			//			ipAddrs <- ips[i] + ":" + strconv.Itoa(ports[j])
			//			ipAddrs := ips[i] + ":" + strconv.Itoa(ports[j])
			m1[ips[i]] = ports[j]
		}
	}
	//	fmt.Print(slice1)
	return m1
	//	close(ipAddrs)
}

权限设计:

//2.如果登录或ip在允许范围内,进行访问权限检查
		uname, role, _ = checkRoleread(c.Ctx) //login里的
		rolename, _ = strconv.Atoi(role)
		c.Data["Uname"] = uname
//检查是否登录或ip在预设允许范围内
func checkAccount(ctx *context.Context) bool {
	var user models.User
	//(4)获取当前的请求会话,并返回当前请求会话的对象
	//但是我还是建议大家采用 SetSession、GetSession、DelSession 三个方法来操作,避免自己在操作的过程中资源没释放的问题
	sess, _ := globalSessions.SessionStart(ctx.ResponseWriter, ctx.Request)
	defer sess.SessionRelease(ctx.ResponseWriter)
	v := sess.Get("uname")
	if v == nil {
		role1 := Getiprole(ctx.Input.IP())
		if role1 != 0 {
			return true
		} else {
			return false
		}
	} else {
		user.Username = v.(string)
		v = sess.Get("pwd")        //没必要检查密码吧,因为只有登录了才产生session,才能获取用户名
		user.Password = v.(string) //ck.Value
		err := models.ValidateUser(user)
		if err == nil {
			return true
		} else {
			return false
		}
	}
}

//访问(读取)权限检查
func checkRoleread(ctx *context.Context) (uname, role string, err error) { //这里返回用户的role
	var user models.User
	var roles []*models.Role
	//(4)获取当前的请求会话,并返回当前请求会话的对象
	sess, _ := globalSessions.SessionStart(ctx.ResponseWriter, ctx.Request)
	defer sess.SessionRelease(ctx.ResponseWriter)
	v := sess.Get("uname")
	if v != nil {
		user.Username = v.(string) //ck.Value
		roles, _, err = models.GetRoleByUsername(user.Username)
		if err == nil {
			return v.(string), roles[0].Title, err //这里修改Name改为title就对了
		} else {
			return v.(string), "5", err
		}
	} else {
		role1 := Getiprole(ctx.Input.IP())
		if role1 != 0 {
			return ctx.Input.IP(), strconv.Itoa(role1), nil
		} else {
			return ctx.Input.IP(), "5", nil
		}

	}
}

//写权限检查——只能是登录用户
func checkRolewrite(ctx *context.Context) (uname, role string, err error) { //这里返回用户的role
	var user models.User
	var roles []*models.Role
	//(4)获取当前的请求会话,并返回当前请求会话的对象
	sess, _ := globalSessions.SessionStart(ctx.ResponseWriter, ctx.Request)
	defer sess.SessionRelease(ctx.ResponseWriter)
	v := sess.Get("uname")
	if v != nil {
		user.Username = v.(string) //ck.Value
		roles, _, err = models.GetRoleByUsername(user.Username)
		if err == nil {
			return v.(string), roles[0].Title, err //这里修改Name改为title就对了
		} else {
			return v.(string), "5", err
		}
	} else {
		return "", "5", err
	}
	// ck, err := ctx.Request.Cookie("uname")
	// if err != nil {
	// }
}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏计算机编程

关于RxJS 自定义封装Rxbus的使用规范文档

2.3、声明isInner为true的情况: 主要是在push页面之前,即进入子页面:

21820
来自专栏娱乐心理测试

一个 JS 库就能解决小程序跨页传递事件消息和数据

由于微信小程序 wx.navigateBack 方法并不支持返回传值,导致页面在返回后,不能方便地即时更新数据。

27840
来自专栏大内老A

ASP.NET MVC集成EntLib实现“自动化”异常处理[实例篇]

个人觉得异常处理对于程序员来说是最为熟悉的同时也是最难掌握的。说它熟悉,因为仅仅就是try/catch/finally而已。说它难以掌握,则是因为很多开发人员却...

230100
来自专栏Golang语言社区

go http 服务器编程(1)

1. 初识 http 是典型的 C/S 架构,客户端向服务端发送请求(request),服务端做出应答(response)。 golang 的标准库 net/h...

3K70
来自专栏攻城狮的动态

iOS面试题梳理(三)

40770
来自专栏Golang语言社区

package http

要管理代理、TLS配置、keep-alive、压缩和其他设置,创建一个Transport:

25340
来自专栏偏前端工程师的驿站

.Net魔法堂:log4net详解

一、作用                              提供一个记录日志的框架,可以将日志信息记录到文件、控制台、Windows事件日志和数据库(M...

22650
来自专栏偏前端工程师的驿站

.Net魔法堂:log4net详解

一、作用                              提供一个记录日志的框架,可以将日志信息记录到文件、控制台、Windows事件日志和数据库(M...

30990
来自专栏菩提树下的杨过

FluorineFx:认证与授权

对认证与授权没啥概念的新同学,建议先看下 .net中的认证(authentication)与授权(authorization),然后再继续。 Flash/Fle...

27780
来自专栏恰童鞋骚年

自己动手写三层代码生成器学习总结

  今天看了下老杨的视频教程,写了一把三层代码生成器,理解了一下简单的代码生成器是如何实现的,其重点就在于数据库系统视图。

9040

扫码关注云+社区

领取腾讯云代金券