今日目標 : 完成登陸頁面和角色角色添加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; }
```