一 权限管理 初始版
结构
1.创建rbac应用
2.在models中创建对象
models
from django.db import models
class Permission(models.Model):
"""
权限表
"""
title = models.CharField(verbose_name=' 标题 ' ,max_length=32)
url = models.CharField(verbose_name=" 含正则URL " ,max_length=64)
is_menu = models.BooleanField(verbose_name=" 是否是菜单 " )
class Meta:
verbose_name_plural = " 权限表 "
def __str__ (self):
return self.title
class User(models.Model):
"""
用户表
"""
username = models.CharField(verbose_name=' 用户名 ' ,max_length=32)
password = models.CharField(verbose_name=' 密码 ' ,max_length=64)
email = models.CharField(verbose_name=' 邮箱 ' ,max_length=32)
roles = models.ManyToManyField(verbose_name=' 具有的所有角色 ' ,to=" Role " ,blank=True)
class Meta:
verbose_name_plural = " 用户表 "
def __str__ (self):
return self.username
class Role(models.Model):
"""
角色表
"""
title = models.CharField(max_length=32)
permissions = models.ManyToManyField(verbose_name=' 具有的所有权限 ' ,to=' Permission ' ,blank=True)
class Meta:
verbose_name_plural = " 角色表 "
def __str__ (self):
return self.title
models
3.基于Django admin录入权限数据
注意;需要在admin.py 中作如下操作(只针对从用admin导入数据时配置,当然也可以从数据库中直接添加)
from django.contrib import admin
from . import models
admin.site.register(models.Permission)
admin.site.register(models.User)
admin.site.register(models.Role)
4.用户登录程序
根据输入的用户名和密码得到相应的user, 根据user对象获取其拥有的角色和具有的权限并去重并且将权限表中的url放入seesion中,将这部分操作的代码抽取到service包下的init_permission.py 下的init_permission(request,user)方法中,然后在views中调用该方法即可, - 获取当前用户具有的所有权限(去重) - 获取权限中的url,放置到session中
def init_permission(user,request):
"""
初始化权限信息,获取权限信息并放置到session中。
:param user:
:param request:
:return:
"""
permission_list = user.roles.values(' permissions__title ' , ' permissions__url ' , ' permissions__is_menu ' ).distinct()
url_list = []
for item in permission_list:
url_list.append(item[ ' permissions__url ' ])
print (url_list)
request.session[ ' permission_url_list ' ] = url_list
init_permission.py
5.编写中间件
import re
from django.shortcuts import redirect,HttpResponse
from django.conf import settings
class MiddlewareMixin(object):
def __init__ (self, get_response=None):
self.get_response = get_response
super(MiddlewareMixin, self). __init__ ()
def __call__ (self, request):
response = None
if hasattr(self, ' process_request ' ):
response = self.process_request(request)
if not response:
response = self.get_response(request)
if hasattr(self, ' process_response ' ):
response = self.process_response(request, response)
return response
class RbacMiddleware(MiddlewareMixin):
def process_request(self,request):
# 1. 获取当前请求的URL
# request.path_info
# 2. 获取Session中保存当前用户的权限
# request.session.get("permission_url_list')
current_url = request.path_info
# 当前请求不需要执行权限验证(白名单)
for url in settings.VALID_URL:
if re.match(url,current_url):
return None
permission_list = request.session.get(" permission_url_list " )
if not permission_list:
return redirect(' /login/ ' )
flag = False
for db_url in permission_list:
regax = " ^{0}$ " .format(db_url)
if re.match(regax, current_url):
flag = True
break
if not flag:
return HttpResponse(' 无权访问 ' )
rbac.py
a,获取当前访问的路径 request.path_info b,在setting中配置不需要验证的url--白名单(人人登录后就可以访问的如login admin.*)然后调用
VALID_URL = [
" /login/ " ,
" /admin.* "
]
根据正则判断当前路径是否在白名单中,白名单中的路径要严格的控制以什么开头和以什么结尾,如果是白名单return None 继续执行后面的代码 如果不是直接跳转到登录 c,不是白名单的话,则判断是否已经登录,最简单的方法就是获取当前session 看是里面的url列表是否为空,如果为空的话说明没有登录,直接 调转到登陆,不让他执行后续操作 d,url list不为空的话就说明已经登陆了,进一步看当前的访问路径是否在是否在urllist中,在的话就说明用户具有操作该url的权限否则就说明该用户没有 访问权限,直接return HttpResponse("无权访问") 注意:中间件创建完成之后。需要在settings中的MIDDLEWARE最后添加'rbac.middlewares.rbac.RbacMiddleware',
MIDDLEWARE = [
' django.middleware.security.SecurityMiddleware ' ,
' django.contrib.sessions.middleware.SessionMiddleware ' ,
' django.middleware.common.CommonMiddleware ' ,
' django.middleware.csrf.CsrfViewMiddleware ' ,
' django.contrib.auth.middleware.AuthenticationMiddleware ' ,
' django.contrib.messages.middleware.MessageMiddleware ' ,
' django.middleware.clickjacking.XFrameOptionsMiddleware ' ,
'rbac.middlewares.rbac.RbacMiddleware',
]
示例一权限管理 加强
对于权限管理,不单单的只是控制能不能访问某个路径,而且还需要根据用户的权限,当用户访问某个页面时,在页面上展示什么,比如某些用户 虽然能访问首页,但是他没有添加用户的权限,这时就不能将添加按钮展现在首页,而对于具有添加用户权限的用户则需要将添加用户的按钮展示 在首页上
在访问列表页面时,是否需要判断:有无添加权限,有无删除权限,有无编辑权限;
1.在rbac下的models中添加Group类,在权限表中添加code字段和外键group
class Group(models.Model):
"""
权限组
"""
caption = models.CharField(verbose_name=' 组名称 ' ,max_length=16)
class Permission(models.Model):
"""
权限表
"""
title = models.CharField(verbose_name=' 标题 ' ,max_length=32)
url = models.CharField(verbose_name=" 含正则URL " ,max_length=64)
is_menu = models.BooleanField(verbose_name=" 是否是菜单 " )
code = models.CharField(verbose_name=" 代码 " ,max_length=16)
group = models.ForeignKey(verbose_name=' 所属组 ' ,to=" Group " )
class Meta:
verbose_name_plural = " 权限表 "
def __str__ (self):
return self.title
2.在rbac/service/init_permission.py/init_permission类中进行修改
结构化数据模型
data = {
1: {
' codes ' : [' list ' ,' add ' ,' edit ' ,' del ' ],
' urls ' :[
/userinfo/,
/userinfo/add/,
/userinfo/edit/(\d+)/,
/userinfo/del /(\d+)/,
]
},
2: {
' codes ' : [' list ' ,' add ' ,' edit ' ,' del ' ],
' urls ' :[
/userinfo/,
/userinfo/add/,
/userinfo/edit/(\d+)/,
/userinfo/del /(\d+)/,
]
},
}
permission_list = user.roles.values(' permissions__title ' ,
"permissions__code",
' permissions__url ' ,
' permissions__is_menu ' ,
"permissions__group__id" ,
).distinct()
result ={}
for item in permission_list:
groupid =item[" permissions__group__id " ]
code =item[" permissions__code " ]
url =item[" permissions__url " ]
if groupid in result:
result[groupid][ " codes " ].append(code)
result[groupid][ " urls " ].append(url)
else :
result[groupid] ={
" codes " :[code,],
" urls " :[url,]
}
print (result)
request.session[settings.PERMISSIONS_URL_DICT_KEY] = result
3.对中间件进行修改
import re
from django.shortcuts import redirect,HttpResponse
from django.conf import settings
class MiddlewareMixin(object):
def __init__ (self, get_response=None):
self.get_response = get_response
super(MiddlewareMixin, self). __init__ ()
def __call__ (self, request):
response = None
if hasattr(self, ' process_request ' ):
response = self.process_request(request)
if not response:
response = self.get_response(request)
if hasattr(self, ' process_response ' ):
response = self.process_response(request, response)
return response
class RbacMiddleware(MiddlewareMixin):
def process_request(self,request):
# 1. 获取当前请求的URL
# request.path_info
# 2. 获取Session中保存当前用户的权限
# request.session.get("permission_url_list')
current_url = request.path_info
# 当前请求不需要执行权限验证
for url in settings.VALID_URL:
if re.match(url,current_url):
return None
permission_dict = request.session.get(settings.PERMISSION_URL_DICT_KEY)
if not permission_dict:
return redirect(' /login/ ' )
flag = False
for group_id,code_url in permission_dict.items():
for db_url in code_url[' urls ' ]:
regax = " ^{0}$ " .format(db_url)
if re.match(regax, current_url):
request.permission_code_list = code_url[' codes ' ]
flag = True
break
if flag:
break
if not flag:
return HttpResponse(' 无权访问 ' )
rbac.py
4.对views进行操作,是否页面上显示功能按钮:
方法1:在模块中进行判断
{% if " add/edit/del " in request.permission_code_list %}
"">添加/编辑/删除
{ % endif%}
方法二: 在views中利用面向对象
class BasePagePermission(object):
def __init__ (self,code_list):
self.code_list = code_list
def has_add(self):
if " add " in self.code_list:
return True
def has_edit(self):
if ' edit ' in self.code_list:
return True
def has_del(self):
if ' del ' in self.code_list:
return True
def userinfo(request):
page_permission = BasePagePermission(request.permission_code_list)
data_list = [
{ ' id ' :1,' name ' :' xxx1 ' },
{ ' id ' :2,' name ' :' xxx2 ' },
{ ' id ' :3,' name ' :' xxx3 ' },
{ ' id ' :4,' name ' :' xxx4 ' },
{ ' id ' :5,' name ' :' xxx5 ' },
]
return render(request,' userinfo.html ' ,{' data_list ' :data_list,' page_permission ' :page_permission})
5.模块中进行判断
{% if pagepermission.has_add %}
"">添加
{ % endif %}
示例二 菜单展示
1.在models中添加Menu对象(表)以及和Group建立起一对多的对应关系
from django.db import models
class Menu(models.Model):
"""
菜单组
"""
title = models.CharField(max_length=32)
class Group(models.Model):
"""
权限组
"""
caption = models.CharField(verbose_name=' 组名称 ' ,max_length=16)
menu = models.ForeignKey(verbose_name=' 所属菜单 ' ,to=' Menu ' )
class Permission(models.Model):
"""
权限表
"""
title = models.CharField(verbose_name=' 标题 ' ,max_length=32)
url = models.CharField(verbose_name=" 含正则URL " ,max_length=64)
is_menu = models.BooleanField(verbose_name=" 是否是菜单 " )
code = models.CharField(verbose_name=" 代码 " ,max_length=16)
group = models.ForeignKey(verbose_name=' 所属组 ' ,to=" Group " )
class Meta:
verbose_name_plural = " 权限表 "
def __str__ (self):
return self.title
class User(models.Model):
"""
用户表
"""
username = models.CharField(verbose_name=' 用户名 ' ,max_length=32)
password = models.CharField(verbose_name=' 密码 ' ,max_length=64)
email = models.CharField(verbose_name=' 邮箱 ' ,max_length=32)
roles = models.ManyToManyField(verbose_name=' 具有的所有角色 ' ,to=" Role " ,blank=True)
class Meta:
verbose_name_plural = " 用户表 "
def __str__ (self):
return self.username
class Role(models.Model):
"""
角色表
"""
title = models.CharField(max_length=32)
permissions = models.ManyToManyField(verbose_name=' 具有的所有权限 ' ,to=' Permission ' ,blank=True)
class Meta:
verbose_name_plural = " 角色表 "
def __str__ (self):
return self.title
models
2.- 初始化: 获取菜单信息+权限信息
from django.conf import settings
def init_permission(user,request):
"""
初始化权限信息,获取权限信息并放置到session中。
:param user:
:param request:
:return:
"""
permission_list = user.roles.values(' permissions__title ' , # 用户列表
' permissions__url ' ,
' permissions__code ' ,
' permissions__is_menu ' , # 是否是菜单
' permissions__group_id ' ,
' permissions__group__menu_id ' , # 菜单ID
' permissions__group__menu__title ' ,# 菜单名称
).distinct()
menu_list = []
# 去掉不是菜单的URL
for item in permission_list:
if not item[' permissions__is_menu ' ]:
continue
tpl = {
' menu_id ' :item[' permissions__group__menu_id ' ],
' menu_title ' :item[' permissions__group__menu__title ' ],
' title ' :item[' permissions__title ' ],
' url ' :item[' permissions__url ' ],
' active ' :False,
}
menu_list.append(tpl)
request.session[settings.PERMISSION_MENU_KEY] = menu_list
# 权限相关
result = {}
for item in permission_list:
group_id = item[' permissions__group_id ' ]
code = item[' permissions__code ' ]
url = item[' permissions__url ' ]
if group_id in result:
result[group_id][ ' codes ' ].append(code)
result[group_id][ ' urls ' ].append(url)
else :
result[group_id] = {
' codes ' :[code,],
' urls ' :[url,]
}
request.session[settings.PERMISSION_URL_DICT_KEY] = result
init_permission.py
结构化数据 示例;
mport re
menu_list = [
{ ' menu_id ' :1, ' menu_title ' :' 菜单一 ' ,' title ' :' 用户列表 ' ,' url ' :' /userinfo/ ' ,' active ' :False},
{ ' menu_id ' :1, ' menu_title ' :' 菜单一 ' ,' title ' :' 订单列表 ' ,' url ' :' /order/ ' ,' active ' :False},
{ ' menu_id ' :2, ' menu_title ' :' 菜单二 ' ,' title ' :' xxx列表 ' ,' url ' :' /xxx/ ' ,' active ' :False},
{ ' menu_id ' :2, ' menu_title ' :' 菜单二 ' ,' title ' :' iii列表 ' ,' url ' :' /uuu/ ' ,' active ' :False},
]
current_url = " /userinfo/ "
res ={}
for tem in menu_list:
mid =tem[" menu_id " ]
mtitle =tem[" menu_title " ]
title =tem[" title " ]
url =tem[" url " ]
active =False
if re.match(url,current_url):
active =True
if mid in res:
res[mid][ " children " ].append({" title " :title," url " :url," active " :active})
if active:
res[mid][ " active " ]=True
else :
res[mid] ={
" menu_id " :mid,
" menu_title " :mtitle,
" active " :active,
" children " :[
{ " title " :title," url " :url," active " :True},
]
}
print (res)
结果:
aa={
1:
{
' menu_id ' : 1,
' menu_title ' : ' 菜单一 ' ,
' active ' : True,
' children ' : [{' title ' : ' 用户列表 ' , ' url ' : ' /userinfo/ ' , ' active ' : True},
{ ' title ' : ' 订单列表 ' , ' url ' : ' /order/ ' , ' active ' : True}]
},
2:
{
' menu_id ' : 2,
' menu_title ' : ' 菜单二 ' ,
' active ' : True,
' children ' : [{' title ' : ' xxx列表 ' , ' url ' : ' /xxx/ ' , ' active ' : True},
{ ' title ' : ' iii列表 ' , ' url ' : ' /uuu/ ' , ' active ' : True}]
}
}
3.显示多级菜单
模块中操作 其中菜单部分由自定义标签生产 具体展示页面则用模块继承:如userinfo
a. base.html
{% load rbac %}
"en " >
"UTF-8 " >
Title
"stylesheet " href=" /static/rbac/rbac.css " >
"float: left;width: 20%;height: 900px;background-color: darkgrey " >
{ % menu_html request %}
"float: left;width: 80% " >
{ % block content %}
{ % endblock %}
b. userinfo.html
{% extends " base.html " %}
{ % block content %}
{ % if pagepermission.has_add %}
"">添加
{ % endif %}
id
name
操作
{ % for foo in data_list %}
{{ foo.id }}
{{ foo.name }}
{ % if pagepermission.has_edit %}
"# " >编辑
{ % endif %}
{ % if pagepermission.has_del %}
"# " >删除
{ % endif %}
{ % endfor %}
{ % endblock %}
c.建立自定义标签
rbac/templatetags/rabc.py
import re
from django.template import Library
from django.conf import settings
register = Library()
@register.inclusion_tag( " menuList.html " )
def menu_html(request):
menu_list = request.session[settings.PERMISSION_MENU_KEY]
current_url = request.path_info
result = {}
for item in menu_list:
url = item[' url ' ]
regex = " ^{0}$ " .format(url)
active = False
if re.match(regex,current_url):
active = True
menu_id = item[' menu_id ' ]
if menu_id in result:
result[menu_id][ ' children ' ].append({' title ' : item[' title ' ], ' url ' : item[' url ' ], ' active ' : active})
if active:
result[menu_id][ ' active ' ] = True
else :
result[menu_id] = {
' menu_id ' : menu_id,
' menu_title ' : item[' menu_title ' ],
' active ' : active,
' children ' : [
{ ' title ' : item[' title ' ], ' url ' : item[' url ' ], ' active ' : active},
]
}
return {' menu_dict ' :result}
rbac.py
d. menuList.html
{% for k,item in menu_dict.items %}
class=
" item " >
class=" item_title " >{{ item.menu_title }}
{ %
if item.active %
}
class=
" item_permissions " >
{ %
else %
}
{ % endfor %}
e.相关css和js
在rbac建立static/rbac目录在其中创建rabc.css和rabc.js
.item_permissions{
padding: 3px 10px;
}
.item_permissions a{
display: block;
}
.item_permissions a.active{
color: red;
}
.hide{
display: none;
}
rbac.css
$(function () {
$( " .item_title " ).click(function () {
$(this).next().toggleClass( " hide " )
});
})
rbac.js
四.菜单展示改进
因为当我们对用户部分进行增删改时,用户列表也应该事展开的,但是我们上面所写的当我们点击增加删除编辑按钮时,用户菜单会闭合而不是展开的 对此我们进行了改进
1..在权限表中增加字段menu_gp,并删除is_menu字段
from django.db import models
class Menu(models.Model):
'''
菜单表
'''
title =models.CharField(max_length=32,verbose_name=" 菜单名称 " )
class Group(models.Model):
'''
权限组
'''
caption =models.CharField(max_length=32,verbose_name=" 组名称 " )
menu =models.ForeignKey(verbose_name=" 所属菜单 " ,to=" Menu " ,default=1)
class Permission(models.Model):
"""
权限表
"""
title = models.CharField(verbose_name=' 标题 ' ,max_length=32)
url = models.CharField(verbose_name=" 含正则URL " ,max_length=64)
# is_menu = models.BooleanField(verbose_name="是否是菜单")
menu_gp=models.ForeignKey(verbose_name=" 组内菜单 " ,to=" Permission " ,null=True,blank=True)
code =models.CharField(max_length=32,verbose_name=" 代码 " ,default=" list " )
group =models.ForeignKey(verbose_name=" s所在权限组 " ,to=" Group " ,default=1)
class Meta:
verbose_name_plural = " 权限表 "
def __str__ (self):
return self.title
class User(models.Model):
"""
用户表
"""
username = models.CharField(verbose_name=' 用户名 ' ,max_length=32)
password = models.CharField(verbose_name=' 密码 ' ,max_length=64)
email = models.CharField(verbose_name=' 邮箱 ' ,max_length=32)
roles = models.ManyToManyField(verbose_name=' 具有的所有角色 ' ,to=" Role " ,blank=True)
class Meta:
verbose_name_plural = " 用户表 "
def __str__ (self):
return self.username
class Role(models.Model):
"""
角色表
"""
title = models.CharField(max_length=32)
permissions = models.ManyToManyField(verbose_name=' 具有的所有权限 ' ,to=' Permission ' ,blank=True)
class Meta:
verbose_name_plural = " 角色表 "
def __str__ (self):
return self.title
moedels.py
2.修改初始化中菜单
from django.conf import settings
def init_permission(user,request):
"""
初始化权限信息,获取权限信息并放置到session中。
:param user:
:param request:
:return:
"""
permission_list = user.roles.values(' permissions__title ' ,
" permissions__code " ,
" permissions__id " ,
' permissions__url ' ,
' permissions__menu_gp_id ' ,
" permissions__group__id " ,
" permissions__group__menu_id " ,
" permissions__group__menu__title " ,
).distinct()
menu_list =[]
for item in permission_list:
tpl ={
" id " :item[" permissions__id " ],
" title " :item[" permissions__title " ],
" menu_title " :item[" permissions__group__menu__title " ],
" url " :item[" permissions__url " ],
" menu_id " :item[" permissions__group__menu_id " ],
" menu_gp_id " :item[" permissions__menu_gp_id " ],
}
menu_list.append(tpl)
request.session[settings.PERMISSIONS_MENU_KEY] =menu_list
# menu_list=[]
# for item in permission_list:
# if not item["permissions__is_menu"]:
# continue
#
# tpl={
# "menu_id":item["permissions__group__menu_id"],
# "menu_title":item["permissions__group__menu__title"],
# "title":item["permissions__title"],
# "url":item["permissions__url"],
# "active":False,
# }
#
# menu_list.append(tpl)
# print(menu_list)
# request.session[settings.PERMISSIONS_MENU_KEY]=menu_list
# 权限管理
result={}
for item in permission_list:
groupid =item[" permissions__group__id " ]
code =item[" permissions__code " ]
url =item[" permissions__url " ]
if groupid in result:
result[groupid][ " codes " ].append(code)
result[groupid][ " urls " ].append(url)
else :
result[groupid] ={
" codes " :[code,],
" urls " :[url,]
}
print (result)
request.session[settings.PERMISSIONS_URL_DICT_KEY] = result
init_permission.py
3.修改定义标签
import re
from django.conf import settings
from django.template import Library
register = Library()
@register.inclusion_tag( " menuList.html " )
def menu_html(request):
menu_list =request.session.get(settings.PERMISSIONS_MENU_KEY)
currenturl =request.path_info
menu_dict ={}
for item in menu_list:
if not item[" menu_gp_id " ]:
menu_dict[item[ " id " ]]=item
for item in menu_list:
regex =" ^{0}$ " .format(item[" url " ])
if re.match(regex,currenturl):
menu_gp_id =item[" menu_gp_id " ]
if not menu_gp_id:
menu_dict[item[ " id " ]][" active " ]=True
else :
menu_dict[item[ " menu_gp_id " ]][" active " ]=True
'''
menu_dict={
1: {'id': 1, 'title': '用户列表', 'url': '/userinfo/', 'menu_gp_id': None, 'menu_id': 1, 'menu_title': '菜单管理', 'active': True},
5: {'id': 5, 'title': '订单列表', 'url': '/order/', 'menu_gp_id': None, 'menu_id': 2, 'menu_title': '菜单2'}}
'''
print (menu_dict," 11111111111111111111111111111111111111111111 " )
result = {}
for item in menu_dict.values():
menu_id =item[" menu_id " ]
menu_title =item[" menu_title " ]
active =item.get(" active " )
url =item[" url " ]
title =item[" title " ]
if menu_id in result:
result[menu_id][ " children " ].append({" title " :title," url " :url," active " :active})
if active:
result[menu_id][ " active " ]=True
else :
result[menu_id] ={
" menu_id " :menu_id,
" menu_title " :menu_title,
" active " :active,
" children " :[
{ " title " :title," url " :url," active " :active},
]
}
print (result)
# for item in menu_list:
# menu_id=item["menu_id"]
# menu_title=item["menu_title"]
# title=item["title"]
# url=item["url"]
# active=False
# regex="^{0}$".format(url)
# if re.match(regex,currenturl):
# active=True
#
# if menu_id in result:
# result[menu_id]["children"].append({{"title":title,"url":url,"active":active},})
# if active:
# result[menu_id]["active"]=active
# else:
# result[menu_id]={
# "menu_id":menu_id,
# "menu_title":menu_title,
# "active":active,
# "children":[
# {"title":title,"url":url,"active":active},
# ]
# }
# print(result)
return {" menu_dict " :result}
rbac.py
其他不做修改
你可能感兴趣的:(rbac权限管理)
Linux~MQ
幽默小吴
linux 运维 服务器 java echarts
一、Linux基础命令如何查看当前进程?答:ps-aux或top(实时监控)。如何查找文件?答:find/path-name"filename"或locatefilename。如何查看系统日志?答:tail-f/var/log/syslog或journalctl(Systemd系统)。权限管理如何修改文件权限?答:chmod755filename或chmodu+xfilename。如何修改文件所有
角色访问控制(RBAC)
IT源哥
架构设计和软件设计 user session actor uml access class
角色访问控制(RBAC)引入了Role的概念,目的是为了隔离User(即动作主体,Subject)与Privilege(权限,表示对Resource的一个操作,即Operation+Resource)。Role作为一个用户(User)与权限(Privilege)的代理层,解耦了权限和用户的关系,所有的授权应该给予Role而不是直接给User或Group。Privilege是权限颗粒,由Operat
开发一个ERP(企业资源计划)系统是一个复杂且需要系统化设计的项目,涉及技术选型、模块设计、数据库规划、权限管理、前后端开发等多个环节
星糖曙光
后端语言(node javascript vue等等) 笔记 python devops mysql vue.js
以下是开发ERP系统的关键步骤和示例代码框架,帮助你快速入门。一、核心开发步骤1.需求分析与功能规划目标行业:明确是为制造业、零售业还是通用型企业设计。核心模块:采购管理(供应商、订单、入库)销售管理(客户、订单、出库)库存管理(实时库存、调拨、盘点)财务管理(应收/应付、总账、报表)生产管理(BOM物料清单、工单)人力资源(员工、考勤、薪资)权限管理(角色、数据隔离)2.技术选型前端:React
模块划分的艺术:控制范围与作用范围的平衡
码农技术栈
python java javascript 后端 架构
在软件设计中,模块化是构建复杂系统的基石。良好的模块划分能够提升代码的可读性、可维护性和可复用性。而“模块的作用范围应该在其控制范围之内”这一原则,则是模块划分的精髓所在。一、什么是控制范围和作用范围?控制范围指的是一个模块能够直接影响或控制的其他模块的集合。例如,一个负责用户登录的模块,其控制范围可能包括用户信息验证、权限管理等模块。作用范围指的是一个模块的功能所影响到的数据或系统的范围。例如,
安全测试中的身份认证与访问控制深度解析
进击的雷神
安全性测试
第一部分:基本概念与核心问题1.身份认证与访问控制基础1.1身份认证三要素知识因素(密码、PIN码)持有因素(硬件令牌、手机)生物因素(指纹、面部识别)1.2访问控制模型DAC(自主访问控制)MAC(强制访问控制)RBAC(基于角色的访问控制)2.关键安全机制2.1会话管理要素会话ID生成算法Cookie安全属性(Secure/HttpOnly)会话超时机制2.2权限管理原则最小权限原则(POLP
Web项目测试专题(七)安全性测试
2025年一定要上岸
安全 web安全
概述:安全性测试旨在确保Web应用在设计和实现过程中能够抵御各种安全威胁,保护用户数据和系统资源。步骤:身份验证和授权:测试用户登录、权限管理和会话管理机制,确保只有授权用户能够访问特定资源。数据加密:验证敏感数据(如密码、支付信息)在传输和存储过程中是否经过加密。输入验证:测试所有用户输入点,防止SQL注入、XSS(跨站脚本攻击)等常见攻击。安全头配置:检查HTTP安全头(如CSP、X-Fram
Vue3按钮权限控制:解锁前端安全交互新姿势
Jiaberrr
vue.js 前端 javascript 交互 安全
背景引入在Vue3项目开发中,权限管理是不可或缺的一部分,而按钮权限控制更是其中的关键环节。它就像是一扇精准的“门禁系统”,能够依据用户的角色和权限,决定是否展示或启用特定的按钮,从而保证系统的安全性和用户体验。以一个常见的管理系统为例,系统中存在管理员、普通用户和访客等不同角色。管理员拥有全面的操作权限,能够执行添加、编辑、删除等所有操作;普通用户可能仅具备查看和部分编辑的权限;而访客或许只能进
FISCO BCOS平台的用户权限控制与分类管理
纸鸢666
联盟链 区块链 联盟链 FISCOBCOS
简介在区块链技术日益广泛应用的今天,如何管理与控制不同用户的权限,确保系统的安全性与高效性,成为了区块链平台不可忽视的一部分。FISCOBCOS作为一款高效的联盟链平台,通过细粒度的权限控制机制,提供了对不同用户权限的有效管理。本文将深入探讨FISCOBCOS如何实现用户的权限控制,并对不同用户进行分类与权限管理。1.账户权限控制FISCOBCOS平台通过控制台提供账户生成脚本get_accoun
Apache Doris 2.1.6 版本正式发布
SelectDB技术团队
doris 数据仓库 开源 数据库 大数据
亲爱的社区小伙伴们,ApacheDoris2.1.6版本已于2024年9月10日正式发布。2.1.6版本在Lakehouse、异步物化视图、半结构化数据管理持续升级改进,同时在查询优化器、执行引擎、存储管理、数据导入与导出以及权限管理等方面完成了若干修复。欢迎大家下载使用。官网下载:https://doris.apache.org/GitHub下载:ReleaseApacheDoris2.1.6R
tp3.2.3 权限管理开发步骤
LaughingZhu
ThinkPHp
需要开发以下功能,顺序是:①【添加角色→角色列表】→②【添加节点→节点列表】→③【权限列表→分配权限】→④【添加用户→用户列表】→⑤【Rbac配置】→⑥【登陆】
如何用 Linux 权限管理打造无懈可击的系统?
努力的小T
Linux 云计算运维基础 linux 服务器 网络 运维 云计算
Linux作为一款开源的操作系统,以其强大的权限管理系统著称,为用户提供了一种有效的方式来保护其重要文件和数据的安全性。本文将带您深入了解如何通过Linux权限管理来构建一个更加安全、可靠的操作环境,并提供详细的实操教程。一、权限基础什么是权限?权限是指某个用户对软件资源(包括但不限于文件)的访问与操作权利。Linux系统中,一切皆文件!因此,我们讨论的权限主要指的是文件权限。权限分类普通权限:最
Linux操作系统:基础与文件系统结构研究
暮雨哀尘
Linux的那点事 linux 网络 网络安全 嵌入式 服务器 文件系统 权限
Linux系统基础与文件系统结构研究摘要本文深入探讨了Linux操作系统的常用命令、文件系统结构及其层次标准(FHS),并结合实际应用场景,详细分析了文件和目录操作、文件查看、系统信息查看以及用户和权限管理等核心功能。通过对Linux文件系统层次结构标准的深入剖析,阐述了根目录及其子目录的作用,并通过实验验证了常用命令的实际应用效果。本文旨在为Linux初学者提供一个全面的入门指南,同时也为有一定
电脑文件防泄密系统
Tianrui Green Shield
天锐绿盾 电脑文件防泄密系统 办公加密软件 源代码防泄密 设计图纸图档保护 办公文件资料加密 电脑行为审计监控 文档安全管理
天锐绿盾电脑文件防泄密系统是一款专业的数据安全防护软件,旨在为企业和个人用户提供全方位的文件保密和防泄密解决方案。以下是对该系统的详细介绍:一、系统概述天锐绿盾防泄密系统通过先进的加密技术和精细的权限管理,确保企业内部的敏感文件在创建、存储、传输和使用过程中始终处于受控状态。该系统支持多种文件格式,如文档、图纸、源代码等,并能在不影响员工正常工作的前提下,实现文件的透明加密和自动解密。二、核心功能
使用Confluence进行知识管理和协作
eahba
java 前端 服务器 python
使用Confluence进行知识管理和协作技术背景介绍Confluence是一个由Atlassian开发的企业级wiki协作平台,主要用于保存和组织项目相关的资料。它不仅是一个强大的知识库,还能高效处理内容管理任务,使团队协作更加便捷。核心原理解析Confluence允许团队创建、共享、存储和检索各种类型的文档。其核心功能包括页面创建、评论、标签、权限管理等。这使得团队成员能够在集中的平台上共同编
Git 安全与权限管理
计算机毕设定制辅导-无忧学长
# Git git 安全
引言在当今软件开发的宏大版图中,Git无疑占据着举足轻重的地位。作为一款分布式版本控制系统,Git以其卓越的特性,为开发者们搭建了高效协作与代码管理的坚实桥梁。它赋予了开发者极大的自主性,即便在离线状态下,也能从容地进行代码的修改、提交等操作,待网络恢复时再与团队成员的代码进行同步。在团队协作的场景里,其分布式特性更是大放异彩,众多开发者能够并行工作,各自在本地开展开发与测试,极大地减少了因等待中
Linux基础学习——指令
是妳流的泪
学习 linux
文章目录Linux的特点Linux的基础指令文件命令1.文件系统导航命令2.文件资源管理命令3.文件权限管理命令4.文件压缩和归档命令软件安装与卸载1.离线安装:dpkg2.在线安装:apt用户相关命令添加与删除用户进程管理命令显示进程状态Linux的特点开源,免费内核可裁剪Linux一切皆文件支持多用户,多任务安全稳定广泛的硬件支持模块化程度高Linux的基础指令文件命令1.文件系统导航命令pw
【Linux-常用命令】Linux 常用命令大全
bmyyyyyy
开发语言 linux 运维 服务器
【Linux-常用命令】Linux常用命令大全1)文件管理1.1.目录操作1.2.vim操作1.3.打包压缩相关命令1.4.Linux管道1.5.Linux远程拷贝命令1.6.查看文件目录大小2)文件权限管理2.1.三种基本权限2.2.更改权限3)运行程序3.1.命令行运行3.2.后台运行3.3.服务方式运行4)系统相关4.1.系统管理命令4.2.防火墙4.3.关机和重启4.4.网络配置5)用户管
基于vue的h5项目之支付宝支付与微信支付
随便的名字
vue vue
一、支付宝h5支付支付宝h5支付操作起来是超级简单的,前端关键代码如下:this.$http.getTradeNo(lastParams).then(res=>{this.$http.doPayAlipay({oid:res.data,//取到的交易订单号url:yourBackUrl//成功后的回调地址}).then(resAlipay=>{//避免时间间隙造成的用户误操作,尽管拿到数据了仍然显
K8S认证工程师(CKA)考试(最新版,实测可靠)
颗粒CloudCoder
docker kubernetes 云计算 linux
k8s的全部考试答案,亲测可靠,博主CKA,CKS已过,欢迎交流。(求个关注吧)1、权限控制RBAC设置配置环境:[candidate@node-1]$kubectlconfiguse-contextk8sContext为部署流水线创建一个新的ClusterRole并将其绑定到范围为特定的namespace的特定ServiceAccount。Task创建一个名为deployment-cluster
小程序笔记
2201_75694264
小程序 笔记 apache
1.小程序全局配置app.json{"pages":["pages/index/index","pages/logs/logs"],"window":{"backgroundTextStyle":"light","navigationBarBackgroundColor":"#fff","navigationBarTitleText":"Weixin","navigationBarTextStyl
基于springboot的文档管理系统
AI架构设计之禅
AI大模型应用入门实战与进阶 DeepSeek R1 & 大数据AI人工智能 计算科学 神经计算 深度学习 神经网络 大数据 人工智能 大型语言模型 AI AGI LLM Java Python 架构设计 Agent RPA
1.背景介绍在当前的企业级开发环境中,文档管理系统显得尤为重要。它不仅能够帮助我们有效地管理和组织各种文档,还能够提供版本控制、权限管理等功能。今天,我将带领大家探索如何使用SpringBoot构建一个高效、易用的文档管理系统。2.核心概念与联系在开始之前,我们需要了解几个核心概念:SpringBoot:SpringBoot是一个基于Spring框架的开源Java开发框架,它可以简化Spring应
如何做好团队文档管理
做好团队文档管理是提高团队效率、避免信息流失和提升协作质量的关键,**通过建立系统化的管理机制、确保文档存取的便捷性、确保信息的准确性、及时性和保密性,可以有效地避免团队成员因文档丢失、混乱或错误而影响工作进展。一个高效的文档管理系统应包括明确的命名规则、权限管理和定期更新的流程。具体来说,一套清晰的文档管理制度不仅能帮助团队成员迅速找到所需文件,还能减少因文档错误而导致的沟通成本和误解。一、明确
第15章 Linux系统权限集中管理项目案例实践
唯美清泠
linux
第15章Linux系统权限集中管理项目案例实践众所周知,Linux系统权限管理是Linux运维工作的重中之重。若服务器不需要团队协作运维管理,那么超级权限可以集中在一人手中,但是很多时候,企业服务器的数量并不止一台,需要很多运维人员共同管理,甚至还需要为开发人员分配管理服务器的用户账号,因此,如何科学地分配和管理,让每个用户既能达到工作要求又不会越权访问(获得工作需求以外的权限)就显得非常重要了,
开源知识管理系统 InfoSphere 2024.1.2 发布
java
推荐一套基于SpringBoot开发的简单、易用的开源权限管理平台,建议下载使用:https://github.com/devlive-community/authx推荐一套为Java开发人员提供方便易用的SDK来与目前提供服务的的OpenAI进行交互组件:https://github.com/devlive-community/openai-java-sdkInfoSphere发布!发布版本发布
开源知识管理系统 InfoSphere 2024.1.3 发布
java
推荐一套基于SpringBoot开发的简单、易用的开源权限管理平台,建议下载使用:https://github.com/devlive-community/authx推荐一套为Java开发人员提供方便易用的SDK来与目前提供服务的的OpenAI进行交互组件:https://github.com/devlive-community/openai-java-sdkInfoSphere发布!发布版本发布
开源 Wiki 系统 InfoSphere 2024.01.1 发布
githubwiki
推荐一套基于SpringBoot开发的简单、易用的开源权限管理平台,建议下载使用:https://github.com/devlive-community/authx推荐一套为Java开发人员提供方便易用的SDK来与目前提供服务的的OpenAI进行交互组件:https://github.com/devlive-community/openai-java-sdkInfoSphere发布!发布版本发布
nginx常用负载均衡策略及使用场景
Biturd
nginx 负载均衡 运维
目录1.轮询(RoundRobin)2.权重(WeightedRoundRobin)3.最少连接(LeastConnections)4.IP哈希(IPHash)5.一致性哈希(Hash)1.轮询(RoundRobin)描述:请求按顺序依次分配到后端服务器。适用场景:适合后端服务器性能较均衡,且业务请求较简单、时间较短的情况,比如静态资源服务等。upstreambackend{serverbacke
Linux系统面经
MySGDLife
Linux与网络编程 linux
文章目录常用命令如何结束进程名为aaa的进程?常用命令文件和目录操作命令:ls、cd、mkdir、pwd、cp、mv、rm文件内容查看和编辑命令:cat、tail、less、more、head、vi系统信息查看命令:ps、top、free、df、du用户和权限管理命令:chmod网络相关命令:tcpudmp、ifconfig、ping、netstat、wgetpwd:显示当前文件路径。cp:用于复
谷歌浏览器重新安装不上的问题:删除注册表无权限
不晚.
chrome windows chrome devtools
第一步:在桌面新建一个.txt文件,输入内容为:WindowsRegistryEditorVersion5.00;WARNING,thisfilewillremoveGoogleChromeregistryentries;fromyourWindowsRegistry.Considerbackingupyourregistrybefore;usingthisfile:http://support.
GaussDB用户权限管理
GottdesKrieges
GaussDB进阶篇 gaussdb oracle 数据库
GaussDB用户权限管理系统权限系统权限查看系统权限授予角色权限角色权限查看角色权限授予对象权限对象权限查看对象权限授予GaussDB数据库中的权限管理可以分为三个级别:系统权限:包括SYSADMIN、CREATEDB、CREATEROLE、AUDITADMIN和LOGIN等权限。角色权限:将一个角色或用户的权限授予一个或多个其他角色或用户。在这种情况下,每个角色或用户都可视为拥有一个或多个数据
基本数据类型和引用类型的初始值
3213213333332132
java基础
package com.array;
/**
* @Description 测试初始值
* @author FuJianyong
* 2015-1-22上午10:31:53
*/
public class ArrayTest {
ArrayTest at;
String str;
byte bt;
short s;
int i;
long
摘抄笔记--《编写高质量代码:改善Java程序的151个建议》
白糖_
高质量代码
记得3年前刚到公司,同桌同事见我无事可做就借我看《编写高质量代码:改善Java程序的151个建议》这本书,当时看了几页没上心就没研究了。到上个月在公司偶然看到,于是乎又找来看看,我的天,真是非常多的干货,对于我这种静不下心的人真是帮助莫大呀。
看完整本书,也记了不少笔记
【备忘】Django 常用命令及最佳实践
dongwei_6688
django
注意:本文基于 Django 1.8.2 版本
生成数据库迁移脚本(python 脚本)
python manage.py makemigrations polls
说明:polls 是你的应用名字,运行该命令时需要根据你的应用名字进行调整
查看该次迁移需要执行的 SQL 语句(只查看语句,并不应用到数据库上):
python manage.p
阶乘算法之一N! 末尾有多少个零
周凡杨
java 算法 阶乘 面试 效率
&n
spring注入servlet
g21121
Spring注入
传统的配置方法是无法将bean或属性直接注入到servlet中的,配置代理servlet亦比较麻烦,这里其实有比较简单的方法,其实就是在servlet的init()方法中加入要注入的内容:
ServletContext application = getServletContext();
WebApplicationContext wac = WebApplicationContextUtil
Jenkins 命令行操作说明文档
510888780
centos
假设Jenkins的URL为http://22.11.140.38:9080/jenkins/
基本的格式为
java
基本的格式为
java -jar jenkins-cli.jar [-s JENKINS_URL] command [options][args]
下面具体介绍各个命令的作用及基本使用方法
1. &nb
UnicodeBlock检测中文用法
布衣凌宇
UnicodeBlock
/** * 判断输入的是汉字 */ public static boolean isChinese(char c) { Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
java下实现调用oracle的存储过程和函数
aijuans
java orale
1.创建表:STOCK_PRICES
2.插入测试数据:
3.建立一个返回游标:
PKG_PUB_UTILS
4.创建和存储过程:P_GET_PRICE
5.创建函数:
6.JAVA调用存储过程返回结果集
JDBCoracle10G_INVO
Velocity Toolbox
antlove
模板 tool box velocity
velocity.VelocityUtil
package velocity;
import org.apache.velocity.Template;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.c
JAVA正则表达式匹配基础
百合不是茶
java 正则表达式的匹配
正则表达式;提高程序的性能,简化代码,提高代码的可读性,简化对字符串的操作
正则表达式的用途;
字符串的匹配
字符串的分割
字符串的查找
字符串的替换
正则表达式的验证语法
[a] //[]表示这个字符只出现一次 ,[a] 表示a只出现一
是否使用EL表达式的配置
bijian1013
jsp web.xml EL EasyTemplate
今天在开发过程中发现一个细节问题,由于前端采用EasyTemplate模板方法实现数据展示,但老是不能正常显示出来。后来发现竟是EL将我的EasyTemplate的${...}解释执行了,导致我的模板不能正常展示后台数据。
网
精通Oracle10编程SQL(1-3)PLSQL基础
bijian1013
oracle 数据库 plsql
--只包含执行部分的PL/SQL块
--set serveroutput off
begin
dbms_output.put_line('Hello,everyone!');
end;
select * from emp;
--包含定义部分和执行部分的PL/SQL块
declare
v_ename varchar2(5);
begin
select
【Nginx三】Nginx作为反向代理服务器
bit1129
nginx
Nginx一个常用的功能是作为代理服务器。代理服务器通常完成如下的功能:
接受客户端请求
将请求转发给被代理的服务器
从被代理的服务器获得响应结果
把响应结果返回给客户端
实例
本文把Nginx配置成一个简单的代理服务器
对于静态的html和图片,直接从Nginx获取
对于动态的页面,例如JSP或者Servlet,Nginx则将请求转发给Res
Plugin execution not covered by lifecycle configuration: org.apache.maven.plugin
blackproof
maven 报错
转:http://stackoverflow.com/questions/6352208/how-to-solve-plugin-execution-not-covered-by-lifecycle-configuration-for-sprin
maven报错:
Plugin execution not covered by lifecycle configuration:
发布docker程序到marathon
ronin47
docker 发布应用
1 发布docker程序到marathon 1.1 搭建私有docker registry 1.1.1 安装docker regisry
docker pull docker-registry
docker run -t -p 5000:5000 docker-registry
下载docker镜像并发布到私有registry
docker pull consol/tomcat-8.0
java-57-用两个栈实现队列&&用两个队列实现一个栈
bylijinnan
java
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/*
* Q 57 用两个栈实现队列
*/
public class QueueImplementByTwoStacks {
private Stack<Integer> stack1;
pr
Nginx配置性能优化
cfyme
nginx
转载地址:http://blog.csdn.net/xifeijian/article/details/20956605
大多数的Nginx安装指南告诉你如下基础知识——通过apt-get安装,修改这里或那里的几行配置,好了,你已经有了一个Web服务器了。而且,在大多数情况下,一个常规安装的nginx对你的网站来说已经能很好地工作了。然而,如果你真的想挤压出Nginx的性能,你必
[JAVA图形图像]JAVA体系需要稳扎稳打,逐步推进图像图形处理技术
comsci
java
对图形图像进行精确处理,需要大量的数学工具,即使是从底层硬件模拟层开始设计,也离不开大量的数学工具包,因为我认为,JAVA语言体系在图形图像处理模块上面的研发工作,需要从开发一些基础的,类似实时数学函数构造器和解析器的软件包入手,而不是急于利用第三方代码工具来实现一个不严格的图形图像处理软件......
&nb
MonkeyRunner的使用
dai_lm
android MonkeyRunner
要使用MonkeyRunner,就要学习使用Python,哎
先抄一段官方doc里的代码
作用是启动一个程序(应该是启动程序默认的Activity),然后按MENU键,并截屏
# Imports the monkeyrunner modules used by this program
from com.android.monkeyrunner import MonkeyRun
Hadoop-- 海量文件的分布式计算处理方案
datamachine
mapreduce hadoop 分布式计算
csdn的一个关于hadoop的分布式处理方案,存档。
原帖:http://blog.csdn.net/calvinxiu/article/details/1506112。
Hadoop 是Google MapReduce的一个Java实现。MapReduce是一种简化的分布式编程模式,让程序自动分布到一个由普通机器组成的超大集群上并发执行。就如同ja
以資料庫驗證登入
dcj3sjt126com
yii
以資料庫驗證登入
由於 Yii 內定的原始框架程式, 採用綁定在UserIdentity.php 的 demo 與 admin 帳號密碼: public function authenticate() { $users=array( &nbs
github做webhooks:[2]php版本自动触发更新
dcj3sjt126com
github git webhooks
上次已经说过了如何在github控制面板做查看url的返回信息了。这次就到了直接贴钩子代码的时候了。
工具/原料
git
github
方法/步骤
在github的setting里面的webhooks里把我们的url地址填进去。
钩子更新的代码如下: error_reportin
Eos开发常用表达式
蕃薯耀
Eos开发 Eos入门 Eos开发常用表达式
Eos开发常用表达式
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
蕃薯耀 2014年8月18日 15:03:35 星期一
&
SpringSecurity3.X--SpEL 表达式
hanqunfeng
SpringSecurity
使用 Spring 表达式语言配置访问控制,要实现这一功能的直接方式是在<http>配置元素上添加 use-expressions 属性:
<http auto-config="true" use-expressions="true">
这样就会在投票器中自动增加一个投票器:org.springframework
Redis vs Memcache
IXHONG
redis
1. Redis中,并不是所有的数据都一直存储在内存中的,这是和Memcached相比一个最大的区别。
2. Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储。
3. Redis支持数据的备份,即master-slave模式的数据备份。
4. Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
Red
Python - 装饰器使用过程中的误区解读
kvhur
JavaScript jquery html5 css
大家都知道装饰器是一个很著名的设计模式,经常被用于AOP(面向切面编程)的场景,较为经典的有插入日志,性能测试,事务处理,Web权限校验, Cache等。
原文链接:http://www.gbtags.com/gb/share/5563.htm
Python语言本身提供了装饰器语法(@),典型的装饰器实现如下:
@function_wrapper
de
架构师之mybatis-----update 带case when 针对多种情况更新
nannan408
case when
1.前言.
如题.
2. 代码.
<update id="batchUpdate" parameterType="java.util.List">
<foreach collection="list" item="list" index=&
Algorithm算法视频教程
栏目记者
Algorithm 算法
课程:Algorithm算法视频教程
百度网盘下载地址: http://pan.baidu.com/s/1qWFjjQW 密码: 2mji
程序写的好不好,还得看算法屌不屌!Algorithm算法博大精深。
一、课程内容:
课时1、算法的基本概念 + Sequential search
课时2、Binary search
课时3、Hash table
课时4、Algor
C语言算法之冒泡排序
qiufeihu
c 算法
任意输入10个数字由小到大进行排序。
代码:
#include <stdio.h>
int main()
{
int i,j,t,a[11]; /*定义变量及数组为基本类型*/
for(i = 1;i < 11;i++){
scanf("%d",&a[i]); /*从键盘中输入10个数*/
}
for
JSP异常处理
wyzuomumu
Web jsp
1.在可能发生异常的网页中通过指令将HTTP请求转发给另一个专门处理异常的网页中:
<%@ page errorPage="errors.jsp"%>
2.在处理异常的网页中做如下声明:
errors.jsp:
<%@ page isErrorPage="true"%>,这样设置完后就可以在网页中直接访问exc