位置:webapp/WEB-INF/views/login.jsp
js代码部分
//登录功能
function submitForm(){
$('#loginForm').form('submit', {
url:"/login",
onSubmit: function(){
return $(this).form('validate');
},
success:function(data){
var result = JSON.parse(data);
if(result.success){
//成功后跳转到主页面
window.location.href = "/main";
}else{
$.messager.alert("提示",result.msg,"error");
}
}
});
}
一个用于跳转(/login,get),一个用于登录(/login,post)
@RequestMapping(value="/login",method = RequestMethod.GET)
public String index(){
return "login";
}
/**
* 是一个Ajax的登录请求,它会返回{success:true/false,msg:xxx}
* @return
*/
@RequestMapping(value="/login",method = RequestMethod.POST)
@ResponseBody
public JsonResult login(String username, String password){
...
}
@RequestMapping(value="/login",method = RequestMethod.POST)
@ResponseBody
public JsonResult login(String username, String password){
//1.拿到当前用户
Subject currentUser = SecurityUtils.getSubject();
//2.如果没有登录,进行登录
if(!currentUser.isAuthenticated()){
//3.准备令牌
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//4.实现登录
try {
currentUser.login(token);
} catch (UnknownAccountException e) {
e.printStackTrace();
return new JsonResult(false, "用户名不存在!");
} catch (IncorrectCredentialsException e) {
e.printStackTrace();
return new JsonResult(false, "账号或密码错误!");
} catch (AuthenticationException e) {
e.printStackTrace();
// System.out.println("就是登录不了(请联系程序员...)");
return new JsonResult(false, "网络出错(联系管理员)!");
}
}
//登录成功成功令牌
return new JsonResult();
}
要有一套自己的密码规则(md5,10次,盐值:itsource)
public class MD5Util {
public static final String SALT = "itsource";
public static final Integer HASHITERATIONS = 10;
//密码加密
public static String changePwd(String password){
SimpleHash hash = new SimpleHash("MD5",password,SALT,HASHITERATIONS);
return hash.toHex();
}
}
controller或者service中都可以进行[我们选择service]
@Override
public void save(Employee employee) {
if(employee.getId()==null){
//添加功能就进行密码修改
employee.setPassword(MD5Util.changePwd(employee.getPassword()));
}
employeeRepository.save(employee);
}
applicationContext-shiro.xml(编码方式与次数)
<bean id="jpaRealm" class="cn.itsource.aisell.shiro.JpaRealm">
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="md5"/>
<property name="hashIterations" value="10" />
bean>
property>
bean>
JpaRealm(加盐一致)
//身份认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//1.拿用户名与密码
UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
String username = token.getUsername();
//2.根据用户名拿到相应的对象
Employee loginUser = employeeService.findByUsername(username);
if(loginUser==null){
return null; //如果用户用空代表用户名不存在
}
String password = loginUser.getPassword();
//返回认证信息
//准备盐值
//传的第一个值就是主体(username名称做的主体)
ByteSource salt = ByteSource.Util.bytes(MD5Util.SALT);
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,salt,getName());
return authenticationInfo;
}
有些地方没有登录也可以直接使用(FilterChainDefinitionMapFactory)
public Map<String,String> createFilterChainDefinitionMap(){
//注:LinkedHashMap是有序的
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/s/login.jsp", "anon");
filterChainDefinitionMap.put("/login", "anon");
//把所有静态资源进行放行
filterChainDefinitionMap.put("*.js", "anon");
filterChainDefinitionMap.put("*.css", "anon");
filterChainDefinitionMap.put("/easyui/**", "anon");
filterChainDefinitionMap.put("/images/**", "anon");
filterChainDefinitionMap.put("/js/**", "anon");
filterChainDefinitionMap.put("/s/permission.jsp", "perms[user:index]");
filterChainDefinitionMap.put("/**", "authc");
return filterChainDefinitionMap;
}
login.jsp
// 检查自己是否是顶级页面
if (top != window) {// 如果不是顶级
//把子页面的地址,赋值给顶级页面显示
window.top.location.href = window.location.href;
}
login.jsp
$(document.documentElement).on("keyup", function(event) {
//console.debug(event.keyCode);
var keyCode = event.keyCode;
console.debug(keyCode);
if (keyCode === 13) { // 捕获回车
submitForm(); // 提交表单
}
});
main.jsp
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
...
<div style="text-align: right;margin-right: 20px;">
欢迎您,亲爱的用户:<shiro:principal />
<a href="/logout">注销a>
div>
LoginController
@RequestMapping("/logout")
public String logout(){
Subject currentUser = SecurityUtils.getSubject();
currentUser.logout();
return "redirect:/login";
}
先使用代码生成器生成Role,Permission
设置多对多的关系
//Employee
@ManyToMany
@JoinTable(name = "employee_role",
joinColumns = @JoinColumn(name="employee_id"),
inverseJoinColumns = @JoinColumn(name="role_id"))
private Set<Role> roles = new HashSet<>();
//Role
@ManyToMany
@JoinTable(name="role_permission",
joinColumns = @JoinColumn(name="role_id"),
inverseJoinColumns = @JoinColumn(name="permission_id"))
private List<Permission> permissions = new ArrayList<>();
role.jsp
<table id="roleGrid" class="easyui-datagrid" fit="true"
...
">
<thead>
<tr>
...
<th data-options="field:'permissions',width:100,formatter:formatPerms">权限th>
tr>
thead>
table>
role.js
//返回权限展示的方法
//v:当前数据 r:当前行数据 i:行索引
function formatPerms(v,r,i){
var permsName = "";
for(let o of v){
permsName += o.name +" ";
}
return permsName;
}
左(当前权限)右(所有权限)都有一个grid
<div id="editDlg" class="easyui-dialog" title="功能操作"
data-options="iconCls:'icon-save',closed:true,modal:true"
style="padding:10px;width: 850px;">
<form id="editForm" method="post">
<input id="roleId" name="id" type="hidden"/>
<table cellpadding="5">
<tr>
<td>
名称:<input class="easyui-validatebox" type="" name="name"
data-options="required:true">input>
编码:<input class="easyui-validatebox" type="text" name="sn"
data-options="required:true">input>
td>
tr>
table>
<div class="easyui-layout" style="width:100%;height:400px;">
<div data-options="region:'west'" style="width:50%;">
<table id="rolePermissionGrid">
<thead>
<tr>
<th data-options="field:'name',width:100">名称th>
<th data-options="field:'sn',width:100">编码th>
<th data-options="field:'url',width:100">资源路径th>
tr>
thead>
table>
div>
<div data-options="region:'center'">
<table id="allPermissionGrid">
<thead>
<tr>
<th data-options="field:'name',width:100">名称th>
<th data-options="field:'sn',width:100">编码th>
<th data-options="field:'url',width:100">资源路径th>
tr>
thead>
table>
div>
div>
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="$('#editDlg').dialog('close')">关闭a>
div>
div>
...
var rolePermissionGrid = $("#rolePermissionGrid");
var allPermissionGrid = $("#allPermissionGrid");
...
itsource = {
add(){
...
//清空grid中的数据
//loadData:加载本地数据,旧的行将被移除
rolePermissionGrid.datagrid("loadData",[]);
...
},
edit(){
...
if(row){
...
//拷备对应的权限数组
var copyPerms = [...row.permissions];
//解决Grid加显问题
rolePermissionGrid.datagrid("loadData",copyPerms);
}else {
...
},
//通过javascript进行保存
save(){
...
editForm.form('submit', {
//form提交的路径
url:url,
//提交之前你要做什么事件
onSubmit: function(param){
//添加一些提交的额外参数
//1.拿到grid中所有的值
var allRows = rolePermissionGrid.datagrid("getRows");
//2.循环把值放进去
for(var i=0;i<allRows.length;i++){
var row = allRows[i];
param[`permissions[${i}].id`] = row.id;
}
return $(this).form('validate');
},
...
});
},
...
//添加一个权限
addPerms(index, row){
//先拿到角色的所有权限
var allRows = rolePermissionGrid.datagrid("getRows");
//遍历进行比较
for(let o of allRows){
//如果两个权限相等,就什么都不做了
if(o.id == row.id){
$.messager.show({
title:'注意事项',
msg:'这个权限已经存在,无需再进行添加!',
timeout:2000,
showType:'slide'
});
return;
}
}
rolePermissionGrid.datagrid("appendRow",row);
},
//删除对应权限
delPerms(index,row){
rolePermissionGrid.datagrid("deleteRow",index);
}
};
//创建当前角色对应的权限(grid控件)
rolePermissionGrid.datagrid({
fit:true,
fitColumns:true,
singleSelect:true,
border:false,
onDblClickRow:itsource.delPerms
})
//创建拿到所有的权限的grid控件
allPermissionGrid.datagrid({
fit:true,
url:'/permission/page',
fitColumns:true,
singleSelect:true,
pagination:true,
border:false,
onDblClickRow:itsource.addPerms
})
修改的时候只能添加不能减少
@ModelAttribute("editRole")
public Role beforeEdit(Long id,String cmd){
//修改的时候才查询(只要有id会就进行一次查询,这是不对的)
if(id!=null && "update".equals(cmd)) {
Role role = roleService.findOne(id);
//把要传过来的关联对象都清空,就可以解决n-to-n的问题
role.getPermissions().clear();
return role;
}
return null;
}