智能供銷系統5_登陸界面,角色

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

```

相關文章
相關標籤/搜索