一 权限管理 初始版
结构
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权限管理)
车载软件调试工具系列---Trace32简介(Lauterbach TRACE32)开头篇
车载诊断技术
车载电子电气架构 车载软件架构——AUTOSAR 架构 AUTOSAR 汽车 电子电器架构 Trace 32 劳特巴赫
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师:屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节能减排。无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事.而不是让内心的烦躁、焦虑、毁掉你本就不多的热情和定力。时间不知不觉中,快
关于项目中使用shiro进行安全管理的总结
一颗大青柠
Java Shiro java spring
关于项目中使用shiro进行安全管理的总结关于SpringBoot下使用shiro进行用户认证与权限管理对于安全框架有一定了解的开发者一定对于shiro这款安全框架有一定的了解,这里我们不再对该框架进行其设计与知识的介绍,仅对于我的个人项目中所使用到的进行一个总结,并放上代码。使用该框架的第一步,进行配置:packagecom.libvirtjava.demo.vm.util.config;imp
MySQL用户权限管理
hzw0510
MySQL mysql oracle 数据库
创建/授权用户创建用户格式创建用户命令一般格式:createuser[用户名]@[访问地址]identifiedby[密码]举例1:创建zhangsan用户,只是创建用户并没有权限,'localhost'表示只能在本地登录,无法通过远程连接;密码是passwordCREATEUSER'zhangsan'@'localhost'
uniapp H5 关掉全部头部header
qq_39016177
uni-app
uniappH5关掉全部头部header1.进入pages.json文件"globalStyle":{//"navigationStyle":"custom","navigationBarTextStyle":"black","navigationBarTitleText":"","navigationBarBackgroundColor":"#F8F8F8","backgroundColor":
Ubuntu 常用指令和作用解析
神奇椰子
ubuntu linux 运维 浪浪云 centos 云计算 代码规范
Ubuntu常用指令和作用解析Ubuntu是一种常见的Linux发行版,它利用了Unix的力量和开源软件的精神。掌握常用指令可以提高我们在使用Ubuntu时的效率。本文将介绍一些常见的指令及其用途。目录更新与安装软件文件与目录操作系统信息与资源监控用户与权限管理网络相关操作更新与安装软件1.1更新软件仓库sudoaptupdate作用:更新本地的包列表,以获取最新的可用包信息。1.2升级系统sud
C# WPF中的GUI多线程技巧详解
zls365365
c# wpf 开发语言
1.使用BackgroundWorker组件代码示例:publicpartialclassMainWindow:Window{privateBackgroundWorkerbackgroundWorker=newBackgroundWorker();publicMainWindow(){InitializeComponent();backgroundWorker.DoWork+=Backgroun
Linux文件权限管理
不屈的铝合金
边学边记-linux linux 服务器 运维 centos
1.文件权限位说明Linux文件或目录的基本权限位是由九个字符来控制的,每三位字符为一组。前三位是用户权限位中三位表示用户组权限位后三位表示其他用户权限位rwxr-xr-xuser(用户)group(用户组)others(其他用户)代表字符为u代表字符为g代表字符为o2.文件权限详细说明2.1普通文件对应权限的详细说明Linux系统中的权限对于文件和目录来说,是有一定区别的。普通文件对应的权限:权
oracle用户管理
sinat_38878030
第二章Oracle用户管理【目标】1.掌握用户的创建、删除、修改2.掌握基本的权限管理3.了解数据字典及基本操作【内容】一、用户的创建、删除、修改u创建用户语法:createuser用户名identifiedby密码;注:在oracle中创建用户只能由管理员或者具有管理员的权限的用户创建。案例:新建用户abc新建的用户是没有任何权限的,包括连接数据库的权限。新创建的用户是没有任何权限的,直接登录会
linux运维常见命令行
问道飞鱼
运维 linux 服务器
文章目录用户管理创建用户修改用户信息列出用户信息添加用户到组删除用户创建和管理组查看用户和组的信息其他相关命令文件管理文件和目录的基本操作文件权限管理文件压缩和归档磁盘管理查看磁盘使用情况查看文件和目录的磁盘使用情况磁盘分区管理挂载和卸载文件系统磁盘配额管理LVM(LogicalVolumeManager)管理网络管理查看网络接口状态配置网络接口查看和管理路由表管理DNS和主机名网络诊断工具网络流
Linux-文件权限管理
蜡笔晴天
linux 运维 服务器
目录目录前言Linux用户权限解析1.基本权限UGO1.1设置权限:2.高级权限2.1suid2.2sgid2.3sbit2.4sudo给普通用户提权3.特殊权限4.隐藏权限总结前言linux服务器上有严格的权限等级,如果权限过高导致误操作会增加服务器的风险。所以对于了解linux系统中的各种权限及要给用户,服务等分配合理的权限十分重要。文件权限大致分为基本权限、高级权限、特殊权限和隐藏权限,下面
linux-用户与权限管理-用户管理
Flying_Fish_Xuan
linux 运维 服务器
Linux用户与权限管理——用户管理详解在Linux系统中,用户管理和权限控制是保证系统安全和资源有效利用的基础。用户管理涉及到创建用户、删除用户、修改用户属性、用户组管理等内容。1.Linux用户体系概述在Linux系统中,所有操作都与用户相关联。用户可以是人、进程或系统程序,操作系统通过用户身份来进行权限和资源的分配。Linux系统将用户分为以下几类:超级用户(Superuser):通常是ro
Gin-Web: 简洁高效的Golang Web框架
黎情卉Desired
Gin-Web:简洁高效的GolangWeb框架gin-web由gin+gorm+jwt+casbin组合实现的RBAC权限管理脚手架Golang版,搭建完成即可快速、高效投入业务开发项目地址:https://gitcode.com/gh_mirrors/gi/gin-web项目简介是一个基于流行的Gin框架构建的增强型Go语言Web开发框架。它旨在提供一套完整的解决方案,包括ORM支持、API文
Ansible Tower与AWX:构建可视化的运维自动化解决方案
勤劳兔码农
运维 ansible 自动化
AnsibleTower与AWX:构建可视化的运维自动化解决方案引言随着企业数字化转型的深入,运维自动化逐渐成为IT管理的重要组成部分。Ansible作为一种简单、灵活且功能强大的自动化工具,广泛应用于配置管理、应用部署和任务自动化中。然而,在大规模、复杂的企业环境中,单纯使用Ansible命令行来管理和执行任务,难以满足对自动化流程的可视化、可审计和权限管理等高级需求。为了解决这些问题,RedH
linux从入门到放弃权限管理,「Linux从入门到放弃」07节-Linux权限介绍
佳丽影像
linux从入门到放弃权限管理
概述我们说Linux较Windows安全的原因之一是Linux的权限设计比Windows系统要严谨可靠。本节比较重要,网络圈会向大家介绍Linux权限知识,运维同学要划下重点哦。请注意:此节会涉及用户、用户组的概念,大家如果对用户(组)不理解没有关系,后面会有单独章节详细解说。权限分类及标识Linux权限可分为下面四种,每种权限可以用特定字母来标识,也可以用特定数字来标识:读权限:r或者4写权限:
(error) ERR auth permission deny
喝醉酒的小白
Redis 运维
分片集群需要新建用户。在Redis分片集群中新建用户的原因通常与安全性和权限管理有关。每个用户可以拥有不同的权限,这样可以限制用户对特定数据的访问,或者允许用户只执行特定的操作。此外,新建用户还可以用于审计和日志记录,以便追踪不同用户的活动。创建用户的具体步骤可能会根据你使用的Redis版本和配置有所不同,但一般来说,你可以在Redis配置文件中设置密码,或者使用ACL(访问控制列表)来创建和管理
Linux基础入门 --8 DAY
安红豆.
Linux学习 linux 运维 服务器
文件权限管理设置文件的所有者chown格式:chown[OPTION]...[OWNER][:[GROUP]]FILE...chown[OPTION]...--reference=RFILEFILE...示例:chownadmin(所有者):admin(所属组)f1.txtchownadmin(所有者).admin(所属组)f1.txtchown--reference=f1.txtf2.txt参考
django(权限、认证)系统——User模型
weixin_30895603
python shell
django(权限、认证)系统——User模型在Django的世界中,在权限管理中有内置的Authentication系统。用来管理帐户,组,和许可。还有基于cookie的用户session。这篇blog主要用来探讨这套内置的Authentication系统。Django内置的权限系统包括以下三个部分:用户(Users)许可(Permissions):用来定义一个用户(user)是否能够做某项任务
Java项目:144 基于springboot医疗报销系统的设计与实现
舒克日记
java java spring boot 开发语言
作者主页:舒克日记简介:Java领域优质创作者、Java项目、学习资料、技术互助文中获取源码项目介绍本医疗报销系统分为管理员还有用户两个权限管理员可以管理用户的基本信息内容,可以管理公告信息以及公告的租赁信息,能够与用户进行相互交流等操作,用户可以查看报销单信息,可以查看公告以及查看管理员回复信息等操作。环境要求1.运行环境:最好是javajdk1.8,我们在这个平台上运行的。其他版本理论上也可以
Node.js 入门:中间件与安全性深度解析
Switch616
前端 node.js 中间件 chrome 服务器 架构 前端 前端框架
Node.js入门:中间件与安全性深度解析目录认证与授权使用jsonwebtoken实现JWT身份验证用户注册与登录:认证流程与实践️权限管理:安全访问控制详解️安全性防止SQL注入:参数化查询与ORM的最佳实践防止XSS攻击:用户输入处理与安全防护使用HTTPS和SSL/TLS:加密传输与数据安全⚠️错误处理️全局错误处理:确保应用稳定性的关键异常捕获与日志记录:有效排查问题的核心认证与授权使用
浅聊kubernetes RBAC
企鹅侠客
云原生 kubernetes 容器 云原生 RBAC
RBAC基于角色(Role)的访问控制(RBAC)是一种基于组织中用户的角色来调节控制对计算机或网络资源的访问的方法。RBAC鉴权机制使用rbac.authorization.k8s.ioAPI组来驱动鉴权决定,允许你通过KubernetesAPI动态配置策略要启用RBAC,在启动API服务器时将--authorization-mode参数设置为一个逗号分隔的列表并确保其中包含RBAC。Role和
JuiceFS 社区版 v1.2 发布,新增企业级权限管理、平滑升级功能
Juicedata
云原生 运维
JuiceFS社区版v1.2今天正式发布,这是自2021年开源以来的第三个大版本。v1.2也是一个长期支持版本(LTS)。我们将持续维护v1.2以及v1.1这两个版本,v1.0将停止更新。JuiceFS是为云环境设计的分布式文件系统,支持超过10种元数据引擎和30种以上的数据存储引擎。这些丰富的选择使得用户可以灵活应对多变的企业环境和数据存储需求;同时,JuiceFS兼容多种访问协议,包括POSI
怎么防止源代码泄漏?十种有效方法防止源代码泄露
cnsinda_htt
源代码加密 源代码防泄漏 源代码防泄密
随着科技的发展,软件已经成为我们日常生活和工作中不可或缺的一部分。然而,软件的安全性问题也日益凸显,尤其是源代码的泄露,可能会导致严重的经济损失和声誉损害。为您提供十种真实有效的方法,帮助您保护源代码的安全。访问控制:实施基于角色的访问控制(RBAC)系统,确保只有授权的员工才能访问源代码。物理安全:将服务器和存储设备放置在安全的物理位置,限制非授权人员的物理接触。数据加密:对源代码文件进行加密,
【实例总结】前端八股文面试
菜鸟una
前端八股文面试题 网络 前端 javascript 微信小程序
综合实例文章目录综合实例1.后台管理权限鉴定方法有哪些?1)基于角色的访问控制(Role-BasedAccessControl,RBAC)2)访问控制列表(AccessControlList,ACL)3)基于属性的访问控制(Attribute-BasedAccessControl,ABAC)4)令牌(Token)和身份验证2.用户登录失效会返回怎么样的结果?1)前端页面显示2)后端API返回3)移
要在nginx中配置后端三个服务器的轮询和加权
小七蒙恩
nginx nginx 服务器 运维
要在nginx中配置后端三个服务器的轮询和加权,你可以按照以下步骤进行配置:打开nginx的配置文件,一般位于/etc/nginx/nginx.conf或/etc/nginx/conf.d/default.conf。在http块内添加一个upstream块用于定义后端服务器列表。例如,我们定义一个名为backend的upstream块:http{upstreambackend{serverback
2022-12-28-PV和PVC简介、使用案例,动静态挂载;
DGFM
PV/PVC简介PV:PersistentVolumePVC:PersistentVolumeClaim用于实现pod和storage的解耦,这样我们在修改存储的同时,不需要修改pod。与NFS的区别,可以在PV和PVC的层面上实现对存储服务器的空间分配,存储权限管理等。kubernetes在1.0版时开始支持PV和PVC。PV:是集群中由kubernetes管理员配置的一个网络存储,一个集群中的
gitlab 包含模型文件,比较大,怎么上传
静心问道
Git gitlab
当你的GitLab项目包含较大的模型文件或其他大文件时,直接上传可能会遇到一些限制。你可以使用以下几种方法来处理:方法1:调整Git的文件大小限制调整GitLab的限制:如果你有权限管理GitLab实例,你可以调整GitLab服务器上的文件大小限制。通常,这是系统管理员的职责。调整Git的buffer大小:如果文件较大但并没有超过GitLab的限制,可以通过调整Git的buffer大小来提高上传效
课程37:Docker持久化部署(数据库、日志、配置文件)
编程乐趣
.Net docker 数据库 容器
前言本文是《.NetCore从零学习搭建权限管理系统》教程专栏的课程(点击链接,跳转到专栏主页,欢迎订阅,持续更新…)专栏介绍:以实战为线索,基于.Net7+REST+Vue、前后端分离,不依赖任何第三方框架,从零一步一步讲解权限管理系统搭建。专栏适用于人群:Web后端开发人员本课程内容:1、Docker持久化问题2、VOLUME持久化:Web、Mysql、Sqlserver持久化3、本地目录映射
使用sa-token 进行权限控制
蜀黍是个小学生
SpringBoot java 后端 spring boot
使用sa-token进行权限控制支持路由鉴权+注解鉴权框架地址:https://sa-token.dev33.cn/项目整体思路:本项目采用RBAC(基于角色的权限访问控制)用户关联多个角色,角色关联菜单/权限。sys_menu表中通过type字段区别是菜单还是权限。通过当前登录用户角色获取对应的菜单集合和权限集合返给前端,前端使用menu表中url或者code码来校验当前页面按钮等相关权限。后端
一篇文章学会oracle数据库角色管理
一心只为学
数据库 oracle
Oracle的权限设置十分复杂,权限分类也很多、很细。就系统权限而言,Oracle的系统权限超过200种。这就为数据库管理员正确有效地管理数据库权限带来了困难,而角色就是简化权限管理的一种数据库对象。一、角色简介角色是一个独立的数据库实体,它包括一组权限。也就是说,角色是包括一个或者多个权限的集合,它并不被哪个用户所拥有。角色可以被授予任何用户,也可以从用户中将角色收回。用角色可以简化权限的管理,
乡村振兴战略下传统村落文化旅游设计 Paperback – Aug. 1 2022 Chinese edition by XU SHAO HUI (Author)
光明理论
旅游 人工智能 媒体 生活 科技 产品运营 内容运营
乡村振兴战略下传统村落文化旅游设计Paperback–Aug.12022ChineseeditionbyXUSHAOHUI(Author)Language:Chinese.paperback.PubDate:2022-08-01.publisher:ChinaBuildingIndustryPress.description:Paperback.PubDate:2022-08-01Pages:20
基本数据类型和引用类型的初始值
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