登录功能
i. 数据库密码修改
准备一个加密算法
public class MD5Util {
// String algorithmName, Object source, Object salt, int hashIterations
//设置盐值
public static final String SALT = "itsource";
//设置遍历次数
public static final int HASHITERATIONS = 10;
//传入一个字符串,返回一个md5编码的值
public static String createMd5Str(String str){
SimpleHash hash = new SimpleHash("MD5",str,SALT,HASHITERATIONS);
return hash.toString();
}
}
通过算法修改数据库密码
@Test
public void testUpdatePwd() throws Exception{
List<Employee> list = employeeService.findAll();
for (Employee employee : list) {
employee.setPassword(MD5Util.createMd5Str(employee.getPassword()));
employeeService.save(employee); //注:save是添加与修改
}
}
添加员工时密码应该加密
EmployeeServiceImpl
@Override
public void save(Employee employee) {
if(employee.getId()==null){
//代表是添加功能(需要进入密码加密)
employee.setPassword(MD5Util.createMd5Str(employee.getPassword()));
}
super.save(employee);
}
ii. 完成登录功能
EmployeeService:提供根据名称查询用户功能
@Override
public Employee findByUsername(String username) {
return employeeRepository.findByUsername(username);
}
JpaRealm:数据库数据
public class JpaRealm extends AuthorizingRealm {
@Autowired
private IEmployeeService employeeService;
。。。
//AuthenticationInfo:认证; 身份验证; 证明
//登录的时候就会调用这个方法来做验证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//身份认证(用户名)
// 1.拿到用户名
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken)token;
String username = usernamePasswordToken.getUsername();
// 2.根据用户名到数据库拿到用户
Employee loginUser = employeeService.findByUsername(username);
if(loginUser==null){
return null; //该用户名不存在
}
//从数据库中拿到密码
Object credentials = loginUser.getPassword();
//加盐的数据
ByteSource byteSource = ByteSource.Util.bytes("itsource");
return new SimpleAuthenticationInfo(loginUser,credentials,byteSource,getName());
}
}
JsonResult:返回数据封装
//封装对象,确定返回值
public class JsonResult {
//是否操作成功
private boolean success = true;
//相应的提示信息
private String msg;
public JsonResult(){}
public JsonResult(boolean success, String msg) {
this.success = success;
this.msg = msg;
}
。。。
}
LoginController:登录功能
@RequestMapping(value="/login",method = RequestMethod.POST)
@ResponseBody
public JsonResult login(String username, String password){
//1.拿到访问的主体(当前登录用户)
Subject subject = SecurityUtils.getSubject();
//2.判断这个用户是否已经登录(通过验证)
if(!subject.isAuthenticated()){
//3.如果没有验证,就要完成登录
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
try{
//4.根据toke完成登录功能
subject.login(token);
}catch (UnknownAccountException e){
System.out.println("用户名不存在!!");
e.printStackTrace();
return new JsonResult(false,"账号或者密码出错!");
}catch (IncorrectCredentialsException e){
System.out.println("密码不存在!");
e.printStackTrace();
return new JsonResult(false,"账号或者密码出错!");
}catch (AuthenticationException e){
System.out.println("登录出错!");
e.printStackTrace();
return new JsonResult(false,"程序发生未知错误!");
}
}
return new JsonResult();
}
login.jsp:登录功能
function submitForm() {
$("#loginForm").form("submit", {
url : "/login",
success : function(data) {
data = $.parseJSON(data);
if (data.success) {
location.href = "/main";
} else {
$.messager.alert("温馨提示", data.msg, "info");
}
}
});
}
function resetForm() {
$("#loginForm").form("clear");
}
iii. 其它功能
回车登录(理解代码即可)
$(document.documentElement).on("keyup", function(event) {
//console.debug(event.keyCode);
var keyCode = event.keyCode;
console.debug(keyCode);
if (keyCode === 13) { // 捕获回车
submitForm(); // 提交表单
}
});
登录过期问题
// 检查自己是否是顶级页面
if (top != window) {// 如果不是顶级
//把子页面的地址,赋值给顶级页面显示
window.top.location.href = window.location.href;
}
展示用户名与注销
main.jsp:在资源中可以找到标签配置
<body class="easyui-layout">
<div data-options="region:'north',split:true" style="height:100px;">
<h1 style="margin-bottom: 10px;">源码时代智销系统</h1>
<div style="text-align: right; margin-right:10px;">
<shiro:user>
欢迎[<shiro:principal
/>]登录,<a href="${pageContext.request.contextPath}/logout">退出</a>
</shiro:user>
</div>
</div>
<div data-options="region:'west',title:'菜单',split:true" style="width:230px;">
<ul id="menuTree"></ul>
</div>
<div id="dataTab" data-options="region:'center'"
class="easyui-tabs" style="padding:5px;background:#eee;">
<div title="Home">
</div>
</div>
</body>
权限domain部分
i. 权限相关实体关系
一个权限只用来控制一个资源。
CREATE TABLE `t_resource` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`url` varchar(255) NOT NULL, 如果是自己拦截换成Controller.方法名,shiro不变
`status` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `t_permission` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(40) NOT NULL,
resourceId
`resource` varchar(80) NOT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
在权限表中添加资源ID外键字段。变形在权限中添加一个资源的字段,不要资源表。
权限与资源之间的多对多
一个权限控制器多个资源,一个资源属于多个权限。
列表部门权限-----列表部门资源,列表员工资源
列表员工资源—列表员工权限,列表部门权限
ii. 创建Domain
<table id="permissionGrid" …>
<thead>
<tr>
<th width="20" field="name" >名称</th>
<th width="20" field="url" >对应的资源</th>
<th width="20" field="sn" >对象的权限</th>
<th width="20" field="descs" >描述</th>
</tr>
</thead>
</table>
<div id="permissionDialog" class="easyui-dialog" data-options="closed:true,modal:true" title="功能操作" style="width:400px">
<div style="padding:10px 60px 20px 40px">
<form id="permissionForm" class="easyui-form" method="post" data-options="">
<input type="hidden" id="permissionId" name="id" >
<table cellpadding="5">
<tr>
<td>名称:</td>
<td><input class="easyui-validatebox" name="name" data-options="required:true"></input></td>
</tr>
<tr>
<td>资源路径:</td>
<td><input class="easyui-validatebox" type="text" name="url" data-options="required:true"></input></td>
</tr>
<tr>
<td>权限:</td>
<td><input class="easyui-validatebox" type="text" name="sn" data-options="required:true"></input></td>
</tr>
<tr>
<td>描述:</td>
<td><input class="easyui-validatebox" type="text" name="descs"></input></td>
</tr>
</table>
</form>
.......
</div>
角色管理(页面功能)
i. 准备角色数据显示
role.jsp
<table id="roleGrid" class="easyui-datagrid" data-options="fit:true,fixed:true,fitColumns:true,toolbar:'#tb',singleSelect:true";
url="/role/page"
iconCls="icon-save"
rownumbers="true" pagination="true">
<thead>
<tr>
<th width="20" field="name" >名称</th>
<th width="20" field="sn" >编码</th>
<th width="20" field="permissions" data-options="formatter:formatperms">权限</th>
</tr>
</thead>
</table>
role.js
function formatperms(val){
var persStr = "" ;
for(var i=0;i<val.length;i++){
var permission = val[i];
persStr += permission.name;
if(i<val.length-1){
persStr+=",";
}
}
return persStr;
}
ii. 添加修改角色
<div id="roleDialog" class="easyui-dialog" data-options="closed:true,modal:true" title="功能操作" style="width:900px">
<div style="padding:10px 60px 20px 40px">
<form id="roleForm" class="easyui-form" method="post" data-options="">
<input type="hidden" id="roleId" name="id" >
<table cellpadding="5" style="width: 100%;">
<tr>
<td>
名称:<input class="easyui-validatebox" type="text" name="name" data-options="required:true"></input>
编码:<input class="easyui-validatebox" type="text" name="sn" data-options="required:true"></input>
</td>
</tr>
<tr>
<td colspan="2">
<div id="cc" class="easyui-layout" style="width: 100%;height:400px;">
<div data-options="region:'west',split:true" style="width:50%;">
<table id="userPermissionGrid">
<thead>
<tr>
<th width="10" field="name" >名称</th>
<th width="20" field="url" >对应的资源</th>
<th width="20" field="sn" >对象的权限</th>
</tr>
</thead>
</table>
</div>
<div data-options="region:'center'" style="padding:5px;background:#eee;">
<table id="allPermissionGrid">
<thead>
<tr>
<th width="10" field="name" >名称</th>
<th width="20" field="url" >对应的资源</th>
<th width="20" field="sn" >对象的权限</th>
</tr>
</thead>
</table>
</div>
</div>
</td>
</tr>
</table>
</form>
<div style="text-align:center;padding:5px">
<a href="javascript:void(0)" class="easyui-linkbutton" data-method="save">提交</a>
<a href="javascript:void(0)" class="easyui-linkbutton" onclick="$('#roleDialog').dialog('close')">取消</a>
</div>
</div>
</div>
role.js
…
//用户权限列表
var userPermissionGrid =$("#userPermissionGrid");
//所有权限列表
var allPermissionGrid =$("#allPermissionGrid");
…
var itsource={
… //添加数据(弹出添加的模态框)
add:function () {
//如果有data-save属性,我们把它展示出来
$("*[data-save]").show();
//启动有data-save属性的input元素的验证功能
$("*[data-save] input").validatebox("enableValidation");
roleForm.form("clear");//清除数据
//弹出表单窗口
roleDialog.dialog("center").dialog('open');
//当前用户权限清空
userPermissionGrid.datagrid("loadData",[]);
},
//修改数据(弹出修改的模态框)
edit:function () {
//选中了某一条数据才删除
var row = roleGrid.datagrid("getSelected");
if(row){
//隐藏有data-save属性的元素
$("*[data-save]").hide();
//禁用有data-save属性的input元素的验证功能
$("*[data-save] input").validatebox("disableValidation");
roleForm.form("clear");//清除数据
roleDialog.dialog("center").dialog('open');
//为form加载数据
roleForm.form("load",row);
//单独解决权限的回显问题(注意,这里要准备一个新的权限,以免删除时出问题)
var permissions = [];
$.extend(permissions,row.permissions);
userPermissionGrid.datagrid("loadData",permissions);
}else{
$.messager.alert('提示信息','请选择一行再进行修改!','info');
}
},
…
//双击所有权限,把一个权限交给这个角色
addPermission:function(rowIndex, rowData){
//判断是否有重复的行
//1.拿到角色权限所有的行数据
var rows = userPermissionGrid.datagrid("getRows");
//2.遍历rows拿到每一个员工数据
for(var i=0;i<rows.length;i++){
var row = rows[i]; //3.判断如果出现相等数据的情况
if(row.id == rowData.id){
//不做任何操作(也可以给出提示)
$.messager.show({
title:'提示',
msg:'该权限已经添加!',
timeout:2000,
showType:'slide'
});
return;
}
}
//把数据加到相应角色权限Grid中
userPermissionGrid.datagrid("appendRow",rowData);
},
//双击后移动相应的权限
removePermission:function (rowIndex, rowData) {
userPermissionGrid.datagrid("deleteRow",rowIndex);
}
}
//我们在这里创建两个Grid
//1.创建当前角色的权限Grid
userPermissionGrid.datagrid({
fit:true,
fixed:true,
fitColumns:true,
//双击后移除权限
onDblClickRow:itsource.removePermission
})
//2.获取所有权限的Grid
allPermissionGrid.datagrid({
fit:true,
fixed:true,
fitColumns:true,
//toolbar:'#tb',
// singleSelect:true";
url:"/permission/page",
rownumbers:"true" ,
pagination:"true",
//双击后添加权限
onDblClickRow:itsource.addPermission
})
iii. 保存数据
var itsource={
//保存数据
save:function () {
var url = "/role/save";
var id = $("#roleId").val();
if(id){
url = "/role/update?cmd=update";
}
roleForm.form('submit', {
url:url,
//这里我们加上params,可以通过这个参数修改咱们的提交数据
onSubmit: function(param){
//得到所有明细
var rows = userPermissionGrid.datagrid("getRows");
//准备传参数据(权限多条数据,是个数组)
//param.permissions = [];
for(var i=0;i<rows.length;i++){
//设置相应的数据值
param["permissions["+i+"].id"] =rows[i].id;
}
//做验证
return roleForm.form("validate");
},
success:function(data){
var result = JSON.parse(data);//转成相应的json数据
if(result.success) {
roleGrid.datagrid('reload');
roleDialog.dialog('close');
}else{
$.messager.alert('提示信息','操作失败!,原因:'+result.msg,"error");
}
}
})
}
}
/**
* 特性:在执行相应方法之前都会先执行这个方法
*/
@ModelAttribute("editRole")
public Role beforeEdit(Long id, String cmd){
//有id的时候-> 修改功能
if(id!=null && "update".equals(cmd)) {
Role role = roleService.findOne(id);
//把这个要修改的关联对象设置为null,可以解决n-to-n的问题
role.getPermissions().clear();
return role;
}
return null;
}