Shiro安全框架
认证,授权,加密,会话管理(单点登录),缓存,与web集成
单点登录(SSO Single Sign on)原理
将原有的各个系统的会话管理机制,抽取出来交给第三方集中实现,这样在访问其他每个系统时,只要从第三方管理的会话信息中,获取用户信息,如果正确,就可以不用再次登录而直接进入系统,这样就可以省去很多登录的时间,提供工作效率
配置
1、jar
2、web.xml配置过滤器
3、auto-proxy代理生成方式,cglib
<!-- shiro生成代理时,使用cglib方式 ,最好放在事务管理器声明之前 -->
<aop:aspectj-autoproxy proxy-target-class="true" />
4、shiro配置文件
1、密码比较器配置
2、自定义realm域的配置
3、缓存的配置
4、shiroFilter的代理子类的配置(web.xml过滤器名称一致)
5、安全管理器的配置
5、编写密码比较器(Md5Hash)
在Md5加密算法的基础上加上盐和打乱次数
明文--》密文
6、编写自定义的Realm域
1、继承AuthorizingRealm
2、重写认证方法,授权方法
7、引入ehcache-shiro.xml缓存
8、总结Shiro执行流程
EL函数的使用
1、导入
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
2、使用
解决页面的样式问题
<style type="text/css">
/*保证在框和文字同一行 并对齐*/
span{display: inline-block;width: 200px}
</style>
get/load
1、get是立即加载,load延迟加载
2、get加载数据失败时返回null,而load加载数据失败会抛出异常
StringBuffer与StringBuilder区别
1、StringBuilder效率高,存在线程安全问题
2、StringBuffer 不存在线程安全问题,效率低
存在多对多关系时,操作其中一方,就可以自动维护中间表的关系,这样就不用配置cascade="all",大多数情况下不配置cascade属性
UserAction
public String torole() throws Exception {
//1、根据id,得到对象
User obj = userService.get(User.class, model.getId());
//2、将对象保存到值栈中
super.push(obj);
//3、调用角色业务方法,得到角色列表
List<Role> roleList = roleService.find("from Role", Role.class, null);
//4、将roleList放入值栈
super.put("roleList", roleList);
//5、得到当前用户的角色列表
Set<Role> roleSet = obj.getRoles();
StringBuilder sb = new StringBuilder();
for(Role role : roleSet) {
sb.append(role.getName()).append(",");//管理员,船运经理,
}
//6、当前用户的角色字符串放入值栈中
super.put("roleStr", sb.toString());
return "torole";
}
角色保存
public String role() throws Exception {
//1、根据用户的id,得到对象
User obj = userService.get(User.class, model.getId());
//2、有哪些角色,只要遍历roleIds,就行
Set<Role> roles = new HashSet<Role>();//当前选中的角色列表
for (String id : roleIds) {
Role role = roleService.get(Role.class,id);
roles.add(role);//向角色列表中添加一个新的角色
}
//3、设置用户与角色列表之间的关系
obj.setRoles(roles);
//4、保存到数据库表中
userService.saveOrUpdate(obj);//影响的是用户角色的中间表
//5、跳页面
return "alist";
}
private String[] roleIds;//保存角色的列表
public void setRoleIds(String[] roleIds) {
this.roleIds = roleIds;
}
2、引入相关的js文件到项目中
http://www.treejs.cn/v3/main.php#_zTreeInfo
自己建个components再建zTree放入 css和js
3、在相关的jsp页面上引入js文件和css样式
<link rel="stylesheet" href="${ctx }/components/zTree/css/zTreeStyle/zTreeStyle.css" type="text/css" />
<script type="text/javascript" src="${ctx }/components/zTree/js/jquery-1.4.4.min.js"></script>
<script type="text/javascript" src="${ctx }/components/zTree/js/jquery.ztree.core-3.5.min.js"></script>
<script type="text/javascript" src="${ctx }/components/zTree/js/jquery.ztree.excheck-3.5.min.js"></script>
4、编写相关的js代码,实现动态生成树(数据源是一个json串)
<script type="text/javascript">
var zTreeObj;
var setting = {
check : {
enable : true
},
data : {
simpleData : {
enable : true
}
}
};
$(document).ready(function() {
/* $.ajax( {
url : "${ctx}/sysadmin/roleAction_roleModuleJsonStr.action?id=${id}",
type : "get",
dataType : "text",
success : initZtree
}); */
$.post(
"${ctx}/sysadmin/roleAction_roleModuleJsonStr.action",
{"id":"${id}"},
function(data){
//var zNodes = eval("(" + data + ")"); //动态js语句
zTreeObj = $.fn.zTree.init($('#jkTree'), setting, data); //jkTree 树的id,支持多个树
zTreeObj.expandAll(true); //展开所有树节点
},
"json"
);
});
//初始化ZTree树
function initZtree(data) {
/* var zNodes = eval("(" + data + ")"); //动态js语句
zTreeObj = $.fn.zTree.init($('#jkTree'), setting, zNodes); //jkTree 树的id,支持多个树
zTreeObj.expandAll(true); //展开所有树节点 */
}
//获取所有选择的节点
function submitCheckedNodes() {
var nodes = new Array();
nodes = zTreeObj.getCheckedNodes(true); //取得选中的结点
var str = "";
for (i = 0; i < nodes.length; i++) {
if (str != "") {
str += ",";
}
str += nodes[i].id;
}
$('#moduleIds').val(str);
}
</script>
5、RoleAction中添加的方法
public String tomodule() throws Exception {
//1、根据角色id,得到角色对象
Role obj = roleService.get(Role.class, model.getId());
//2、保存值栈中
super.push(obj);
//跳页面
return "tomodule";
}
6、配置结果视图
<result name="tomodule">/WEB-INF/pages/sysadmin/role/jRoleModule.jsp</result>
8、客户端接受json串并加载到ztree
zTreeObj = $.fn.zTree.init($('#jkTree'), setting, data); //jkTree 树的id,支持多个树
第一个参数:树展示的位置
第二个参数:一些初始配置
第三个参数:服务器返回的json对象
zTreeObj.expandAll(true); //展开所有树节点
9、获取zTree树上被选中的结点
nodes = zTreeObj.getCheckedNodes(true); //取得选中的结点
可以在表单提交时,把zTree树上选中结点组织成提交的数据
//获取所有选择的节点
function submitCheckedNodes() {
var nodes = new Array();
nodes = zTreeObj.getCheckedNodes(true); //取得选中的结点
var str = "";
for (i = 0; i < nodes.length; i++) {
if (str != "") {
str += ",";
}
str += nodes[i].id;
}
$('#moduleIds').val(str);
}
此函数的调用
<li id="save"><a href="#" onclick="submitCheckedNodes();formSubmit('roleAction_module','_self');this.blur();">保存</a></li>
10、RoleAction保存用户选中的结点
public String module() throws Exception {
//1、哪个角色
Role role = roleService.get(Role.class, model.getId());
//2、选中的模块有哪些
String[] ids = moduleIds.split(",");
//加载出这些模块列表
Set<Module> moduleSet = new HashSet<Module>();
if(ids!=null && ids.length>0) {
for (String id : ids) {
moduleSet.add(moduleService.get(Module.class, id));//添加选中的模块,放到模块列表中
}
}
//3、实现角色分配新的模块
role.setModules(moduleSet);
//4、保存结果
roleService.saveOrUpdate(role);
//5、跳页面
return "alist";
}
private String moduleIds;
public void setModuleIds(String moduleIds) {
this.moduleIds = moduleIds;
}
粗粒度权限控制:只能控制不同角色的用户登录系统时,所看到的主菜单,左侧菜单,按钮,超链接是不同的
11、异常框架
使用struts2处理异常
步骤
1、自定义相关异常类
2、导入异常处理页面
3、在strruts.xml文件中配置
<!--全局结果视图-->
<global-results>
<result name="error">/WEB-INF/pages/error.jsp</result>
</global-results>
<!--全局异常处理-->
<global-exception-mappings>
<exception-mapping exception="my.exception.SysException" result="error"></exception-mapping>
<exception-mapping exception="java.lang.Exception" result="error"></exception-mapping>
</global-exception-mappings>