今日目标 : 完成登陆页面和角色角色添加javascript
[toc]
# 一.登陆
## 1.1 准备登陆页面(随便找一个便可)
> 位置:webapp/WEB-INF/views/login.jspcss
js代码部分
```
//登陆功能java
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"); } } }); }
```web
## 1.2 LoginController功能数据库
### 1.2.1 两个login方法
> 一个用于跳转(/login,get),一个用于登陆(/login,post)```apache
@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){ ... }
```数组
### 1.2.2完成登陆的功能
```app
@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(); }
```webapp
## 1.3 登陆细节jsp
### 1.3.1 数据库的密码设置
> 要有一套本身的密码规则(md5,10次,盐值:xxxxx)
#### a.MD5Util```
public class MD5Util { public static final String SALT = "xxxxx"; public static final Integer HASHITERATIONS = 10; //密码加密 public static String changePwd(String password){ SimpleHash hash = new SimpleHash("MD5",password,SALT,HASHITERATIONS); return hash.toHex(); } }
```
#### b.添加用户密码加密
> controller或者service中均可以进行[咱们选择service]
```
@Override public void save(Employee employee) { if(employee.getId()==null){ //添加功能就进行密码修改 employee.setPassword(MD5Util.changePwd(employee.getPassword())); } employeeRepository.save(employee); }
```
#### c.加密的判断必需和规则一致
> applicationContext-shiro.xml(编码方式与次数)
```
<!-- 被引用的realm(必定会写一个自定义realm) --> <bean id="jpaRealm" class="cn.itsource.aisell.shiro.JpaRealm"> <!-- 为这个realm设置相应的匹配器 --> <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; }
```
### 1.3.2 其它细节#### a.静态资源放行
> 有些地方没有登陆也能够直接使用(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; }
```
#### b.登陆过时
> login.jsp
```
// 检查本身是不是顶级页面 if (top != window) {// 若是不是顶级 //把子页面的地址,赋值给顶级页面显示 window.top.location.href = window.location.href; }
```
#### c.回车登陆
> login.jsp
```
$(document.documentElement).on("keyup", function(event) { //console.debug(event.keyCode); var keyCode = event.keyCode; console.debug(keyCode); if (keyCode === 13) { // 捕获回车 submitForm(); // 提交表单 } });
```
#### d.展现用户名与注销
> 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
>设置多对多的关系(set/List均可以)
```
//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<>();
```
## 2.1 角色中(权限的展现)
> 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; }
```
## 2.1 添加权限
### 2.1.1 form弹出布局
> 左(当前权限)右(全部权限)都有一个grid
```
<!-- 一个弹出框,里面要装一个form表单 --> <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"> <!-- 修改的话,这个id是必需的 --> <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>
```
### 2.1.2 为角色添加/删除权限
```
... 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 })
```
### 2.1.3 只增不减的问题
> 修改的时候只能添加不能减小
```
@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; }
@ModelAttribute("editRole") public Role beforeEdit(Long id,String cmd){ if(id!=null && "_update".equals(cmd)){ //修改才执行这个代码 Role dbRole = roleService.findOne(id); //解决n-to-n的问题,把关联对象设置为null dbRole.getPermissions().clear(); return dbRole; } return null; }
```