1. 程式人生 > >成長記錄貼之springboot+shiro(二) {完成一個完整的許可權控制,詳細步驟}

成長記錄貼之springboot+shiro(二) {完成一個完整的許可權控制,詳細步驟}

       近一個月比較忙,公司接了一個新專案,領導要求用shiro進行安全管理,而且全公司只有我一個java,從專案搭建到具體介面全是一個人再弄。不過剛好前段時間大概學習了一下shiro的使用,還算順利。

       下面將專案中的shiro部分記錄下來,為以後使用做一個備份。(因為是個人測試用的demo,好多地方再設計和實現的時候都是使用了最方便或者最簡單的方法,希望不會誤導各位看官)


*************************專案環境:springboot+jpa+hirbernate+mysql+shiro+maven*************************

前端很簡陋,只是簡單的用到了js,layui和vue,主要是為了方便展示資料


專案環境搭建和資料庫點選這裡檢視,搭建完成後開始具體的許可權管理工作


目錄

專案結構

註冊

1.首先在shiro的大管家ShiroConfig配置類中告訴大管家,註冊的連結不需要攔截。

2.註冊頁面和實現

  2.1註冊頁面

  2.2註冊實現

登入

1.驗證碼

 1.1先pom中新增jar包依賴(我用的Kaptcha,網上大部分都是用這個生成驗證碼)

 1.2在springboot啟動類中注入生成驗證碼的bean()

1.3 寫一個token類,整合shiro提供的UsernamePasswordToken

1.4寫一個獲取驗證碼的攔截器

1.5驗證碼異常類

1.6將驗證碼攔截器配置給shiro

1.7登入controller中增加驗證碼異常判斷

1.8 登入頁面放入驗證碼圖片和驗證碼輸入框

2.密碼校驗

3.許可權校驗

設定資源,角色

1.開啟shiro的資源監控

2.設定使用者角色、許可權

2.1使用者維護

2.2使用者角色資源管理介面

2.3介面



專案結構

註冊

1.首先在shiro的大管家ShiroConfig配置類中告訴大管家,註冊的連結不需要攔截。

       

2.註冊頁面和實現


  2.1註冊頁面


    因為是測試demo我就只寫一個簡單的登入頁面,只需要有一個form表單可以提交賬號密碼就行

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>註冊</title>
</head>
<body>
<form action="/register" method="post">
    使用者名稱:<input type="text" name="username"/>
    <br/>
    密碼:<input type="text" name="password"/>
    <br/>
    姓名:<input type="text" name="name"/>

    <input type="submit" value="註冊"/>
</form>

</body>
</html>

  2.2註冊實現

       這一步主要就是把密碼用md5加鹽加密,將加密後的密碼和鹽值存入資料庫,然後返回登入頁面

        (使用者名稱重名校驗啥的都沒寫,可以根據具體專案增加校驗)

@RequestMapping("/register")
    public String register(UserInfo user) {
       String username=user.getUsername();
       String password1=user.getPassword();
        ByteSource salt = ByteSource.Util.bytes(username);
        String password = new SimpleHash("MD5", password1,username+salt,1024).toString();
        user.setSalt(salt.toString());
        user.setPassword(password);
        byte by=1;
        user.setState(by);
        dao.save(user);
       return "login";
    }

登入

1.驗證碼

 1.1先pom中新增jar包依賴(我用的Kaptcha,網上大部分都是用這個生成驗證碼)

<!-- 驗證碼jar-->
        <dependency>
            <groupId>com.github.penggle</groupId>
            <artifactId>kaptcha</artifactId>
            <version>2.3.2</version>
        </dependency>

 1.2在springboot啟動類中注入生成驗證碼的bean()

 @Bean
    public ServletRegistrationBean kaptchaServlet() {

        ServletRegistrationBean registrationBean = new ServletRegistrationBean(new KaptchaServlet(), "/kaptcha.jpg");

        registrationBean.addInitParameter(Constants.KAPTCHA_SESSION_CONFIG_KEY,
                Constants.KAPTCHA_SESSION_KEY);
        registrationBean.addInitParameter(Constants.KAPTCHA_IMAGE_HEIGHT, "60");//高度
        registrationBean.addInitParameter(Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE, "50");//字型大小
        registrationBean.addInitParameter(Constants.KAPTCHA_BORDER_THICKNESS, "1"); //邊框
        registrationBean.addInitParameter(Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR, "red"); //文字顏色

        //可以設定很多屬性,具體看com.google.code.kaptcha.Constants
//      kaptcha.border  是否有邊框  預設為true  我們可以自己設定yes,no
//      kaptcha.border.color   邊框顏色   預設為Color.BLACK
//      kaptcha.border.thickness  邊框粗細度  預設為1
//      kaptcha.producer.impl   驗證碼生成器  預設為DefaultKaptcha
//      kaptcha.textproducer.impl   驗證碼文字生成器  預設為DefaultTextCreator
//      kaptcha.textproducer.char.string   驗證碼文字字元內容範圍  預設為abcde2345678gfynmnpwx
//      kaptcha.textproducer.char.length   驗證碼文字字元長度  預設為5
//      kaptcha.textproducer.font.names    驗證碼文字字型樣式  預設為new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
//      kaptcha.textproducer.font.size   驗證碼文字字元大小  預設為40
//      kaptcha.textproducer.font.color  驗證碼文字字元顏色  預設為Color.BLACK
//      kaptcha.textproducer.char.space  驗證碼文字字元間距  預設為2
//      kaptcha.noise.impl    驗證碼噪點生成物件  預設為DefaultNoise
//      kaptcha.noise.color   驗證碼噪點顏色   預設為Color.BLACK
//      kaptcha.obscurificator.impl   驗證碼樣式引擎  預設為WaterRipple
//      kaptcha.word.impl   驗證碼文字字元渲染   預設為DefaultWordRenderer
//      kaptcha.background.impl   驗證碼背景生成器   預設為DefaultBackground
//      kaptcha.background.clear.from   驗證碼背景顏色漸進   預設為Color.LIGHT_GRAY
//      kaptcha.background.clear.to   驗證碼背景顏色漸進   預設為Color.WHITE
//      kaptcha.image.width   驗證碼圖片寬度  預設為200
//      kaptcha.image.height  驗證碼圖片高度  預設為50
        return registrationBean;

    }

 

1.3 寫一個token類,整合shiro提供的UsernamePasswordToken

UsernamePasswordToken是shiro提供的使用者令牌,我們擴充套件一下,用來接收使用者輸入的賬號密碼和驗證碼
package com.example.config;

import org.apache.shiro.authc.UsernamePasswordToken;

public class CaptchaUsernamePasswordToken extends UsernamePasswordToken {
    private static final long serivalVersionUID = 1L;

    //驗證碼字串
    private String captcha;

    public CaptchaUsernamePasswordToken(String username, char[] password, boolean rememberMe, String host, String captcha) {
        super(username,password,rememberMe, host);
        this.captcha = captcha;
    }

    public static long getSerivalVersionUID() {
        return serivalVersionUID;
    }

    public String getCaptcha() {
        return captcha;
    }

    public void setCaptcha(String captcha) {
        this.captcha = captcha;
    }


}

1.4寫一個獲取驗證碼的攔截器

攔截到輸入的驗證碼,與系統生成的驗證碼進行匹配,如果驗證碼錯誤則不再校驗使用者名稱和密碼

package com.example.KaptchaFilter;

import com.example.Exception.IncorrectCaptchaException;
import com.example.config.CaptchaUsernamePasswordToken;
import com.google.code.kaptcha.Constants;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public class KaptchaFilter extends FormAuthenticationFilter {

    public static final String DEFAULT_CAPTCHA_PARAM = "captcha";

    private String captchaParam = DEFAULT_CAPTCHA_PARAM;

    @Override
    protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {

        CaptchaUsernamePasswordToken token = createToken(request, response);
        String username = token.getUsername();

        try {
            doCaptchaValidate((HttpServletRequest) request, token);
            Subject subject = getSubject(request, response);
            subject.login(token);
            return onLoginSuccess(token, subject, request, response);

        } catch (AuthenticationException e) {
            return onLoginFailure(token,e,request,response);
        }
    }

    //驗證碼校驗
    protected void doCaptchaValidate(HttpServletRequest request, CaptchaUsernamePasswordToken token) {

        // 從session中獲取圖形嗎字串
        String captcha = (String) request.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);

        // 校驗
        if (captcha == null || !captcha.equals(token.getCaptcha())) {
            throw new IncorrectCaptchaException();
        }
    }

    @Override
    protected CaptchaUsernamePasswordToken createToken(ServletRequest request, ServletResponse response) {

        String username = getUsername(request);
        String password = getPassword(request);
        String host = getHost(request);
        boolean rememberMe = isRememberMe(request);
        String captcha = getCaptcha(request);

        return new CaptchaUsernamePasswordToken(username,password.toCharArray(),rememberMe,host,captcha);
    }

    protected  String getCaptcha(ServletRequest request) {
        return WebUtils.getCleanParam(request, getCaptchaParam());
    }

    //儲存異常物件到request
    @Override
    protected void setFailureAttribute(ServletRequest request, org.apache.shiro.authc.AuthenticationException ae) {
        request.setAttribute(getFailureKeyAttribute(), ae);
    }

    public String getCaptchaParam() {
        return captchaParam;
    }

    public void setCaptchaParam(String captchaParam) {
        this.captchaParam = captchaParam;
    }
}

驗證碼校驗的時候丟擲了一個異常,在homecontroller中會根據登入時shiro校驗完成後的異常,判斷登入狀態和錯誤原因,這個異常就是用來判斷驗證碼是否輸入正確的。

因此我們需要寫一個異常提供給shiro使用

1.5驗證碼異常類

package com.example.Exception;

import org.apache.shiro.authc.AuthenticationException;

public class IncorrectCaptchaException extends AuthenticationException {

    private static final long serivalVersionUID = 1L;

    public IncorrectCaptchaException() {
        super();
    }

    public IncorrectCaptchaException(String message, Throwable cause) {
        super(message, cause);
    }

    public IncorrectCaptchaException(String message) {
        super(message);
    }

    public IncorrectCaptchaException(Throwable cause) {
        super(cause);
    }
}

1.6將驗證碼攔截器配置給shiro

1.7登入controller中增加驗證碼異常判斷

@RequestMapping("/login")
    public String login(HttpServletRequest request, Map<String, Object> map) throws Exception{
        Object ob=SecurityUtils.getSubject().getPrincipal();
        if(ob!=null){

            return "index";
        }
        System.out.println("HomeController.login()");
        // 登入失敗從request中獲取shiro處理的異常資訊。
        // shiroLoginFailure:就是shiro異常類的全類名.
        Object exception =  request.getAttribute("shiroLoginFailure");
        System.out.println("exception=" + exception);
        System.out.println(IncorrectCredentialsException.class.getName());
        String msg = "";
        if (exception != null) {
            if (UnknownAccountException.class.isInstance(exception)) {
                msg = "UnknownAccountException -- > 賬號不存在:";
            } else if (IncorrectCredentialsException.class.isInstance(exception)) {
                msg = "IncorrectCredentialsException -- > 密碼不正確:";
            } else if (IncorrectCaptchaException.class.isInstance(exception)) {
                msg = "kaptchaValidateFailed -- > 驗證碼錯誤";
            } else {
                msg = "else >> "+exception;
            }
        }
        map.put("msg", msg);
        // 此方法不處理登入成功,由shiro進行處理
        return "login";
    }

1.8 登入頁面放入驗證碼圖片和驗證碼輸入框

<div class="layui-inline" style="width: 85%">
                <label class="layui-form-label">驗證碼</label>
                <div  class="layui-inline">
                    <input type="text" id="captcha" name="captcha"   lay-verify="required" placeholder="請輸入驗證碼" autocomplete="off" class="layui-input"/>
                </div>
                <div  class="layui-inline"><img src="kaptcha.jpg" id="kaptchaImage" /></div>
            </div>

2.密碼校驗

這裡需要做的只是將根據使用者輸入的使用者名稱查詢出來的userinfo扔給shiro專門用來校驗密碼的方法doGetAuthenticationInfo,讓shiro自己去驗證就行,關於如何修改shiro的驗證方法,比如修改解密演算法什麼的,在我上一貼中有介紹,這裡就不多說了

點選這裡檢視上一貼

 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
            throws AuthenticationException {
        System.out.println("MyShiroRealm.doGetAuthenticationInfo()");
        //獲取使用者的輸入的賬號.
        String username = (String)token.getPrincipal();
        String password = new String((char[])token.getCredentials()); //得到密碼

        //通過username從資料庫中查詢 User物件,如果找到,沒找到.
        //實際專案中,這裡可以根據實際情況做快取,如果不做,Shiro自己也是有時間間隔機制,2分鐘內不會重複執行該方法
        UserInfo userInfo = userInfoService.findByUsername(username);
        System.out.println("----->>userInfo="+userInfo);
        System.out.print(userInfo.getPassword());
        if(userInfo == null){
            return null;
        }
        /*
         * 獲取許可權資訊:這裡沒有進行實現,
         * 請自行根據UserInfo,Role,Permission進行實現;
         * 獲取之後可以在前端for迴圈顯示所有連結;
         */
        //userInfo.setPermissions(userService.findPermissions(user));
        System.out.println(userInfo.getCredentialsSalt());
        System.out.println(ByteSource.Util.bytes(userInfo.getCredentialsSalt()));
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                userInfo, //使用者名稱
                userInfo.getPassword(), //密碼
                ByteSource.Util.bytes(userInfo.getCredentialsSalt()),//salt=username+salt
                getName()  //realm name
        );
        return authenticationInfo;
    }

3.許可權校驗

       這裡個人理解是shiro提供了一個用來放使用者授權資訊的物件SimpleAuthorizationInfo和一個用來放身份資訊的集合PrincipalCollection。我們從PrincipalCollection中獲取當前登入的使用者物件,因為使用者物件、角色物件、資源物件三者存在關聯關係,在設計資料庫時已經設計好了關聯關係,並且三個物件已經用jpa進行了關了,可以直接從其中一個物件中獲取關聯的其他物件。而shiro的許可權管理不需要我們操作。

        所以這裡的許可權管理只需要從PrincipalCollection中獲取使用者物件,再使用者物件中獲取到角色物件,再從角色物件中獲取資源物件,最後將這些物件放入到SimpleAuthorizationInfo中,讓shiro自己去給我們判斷使用者是否有訪問許可權就可以了

 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        System.out.println("許可權配置-->MyShiroRealm.doGetAuthorizationInfo()");
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();


        UserInfo userInfo  = (UserInfo) principals.getPrimaryPrincipal();
       // BeanUtils.copyProperties(oo,userInfo);


        for(SysRole role:userInfo.getRoleList()){
            authorizationInfo.addRole(role.getRole());
            for(SysPermission p:role.getPermissions()){
                authorizationInfo.addStringPermission(p.getPermission());
            }
        }
        return authorizationInfo;
    }

這裡有一點需要注意,在

UserInfo userInfo  = (UserInfo) principals.getPrimaryPrincipal();

的時候可能會,報com.example.entity.UserInfo cannot be cast to com.example.entity.UserInfo,

在網上找到的辦法是將springboot的熱部署關掉就ok了,但是原理不知道,希望有大佬解答

設定資源,角色

1.開啟shiro的資源監控

我們將需要保護的資源或者連結納入shiro控制的方位內,具體做法就是在controller方法前加上@RequiresPermissions("view")註解,括號裡為資源名稱,與資料庫資源表中的欄位對應。資源名稱支援萬用字元,可以寫成

@RequiresPermissions("userInfo:view") 表示檢視使用者
@RequiresPermissions("userInfo:view,add")表示檢視和增加使用者
@RequiresPermissions("userInfo:view:123")表示只能檢視id為123的使用者 這一點沒有測試,有時間了再測試一下具體用法
@RequestMapping("/userManager")
    @RequiresPermissions("userInfo:manager")//許可權管理;
    public String userManager(){
        return "userInfoManager";
    }

為了能讓系統識別@RequiresPermissions註解,需要在shiroconfig配置中開啟改註解

 @Bean
    @DependsOn("lifecycleBeanPostProcessor")
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }
 @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

 @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }

2.設定使用者角色、許可權

2.1使用者維護

使用者檢視介面

增加一個簡單的使用者查詢介面,用來獲取全部使用者,並可以檢視和分配使用者角色

注:之後的頁面程式碼都是套用的這個頁面,就不貼出來了

<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>UserInfo</title>
    <script type="text/javascript" th:src="@{../static/source/js/layui/layui.js}"></script>
    <script type="text/javascript" th:src="@{../static/source/js/layui/layui.all.js}"></script>
    <script type="text/javascript" th:src="@{../static/vue.min.js}"></script>
    <script type="text/javascript" th:src="@{../static/jquery-3.3.1.min.js}"></script>
    <link rel="stylesheet" th:href="@{../static/source/js/layui/css/layui.css}"/>
</head>
<body>
    <h3>使用者查詢介面</h3>
    <div id="userinfo">
        <table class="layui-table">
            <thead>
            <tr>
                <th>使用者名稱1111</th>
                <th>姓名</th>
                <th>id</th>
                <th>操作</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="site in tablePerson">
                <th>{{site.name}}</th>
                <th>{{site.username}}</th>
                <th>{{site.uid}}</th>
                <th><span @click="changeRole(site.uid)" >檢視</span>
                    <span @click="allotRole(site.uid)" >分配角色</span>
                </th>
            </tr>

            </tbody>
        </table>

    </div>
</body>
<script>
    var userinfo = new Vue({
        el: '#userinfo',
        data: {
            tablePerson: []
        },
        created: function () {
            //為了在內部函式能使用外部函式的this物件,要給它賦值了一個名叫self的變數。
            var self = this;
            var codeurl = "/userInfo/queryUser";
            $.ajax({
                type: 'get',
                url: codeurl,
                async: false,
                contentType: 'application/json;charset=UTF-8',
            }).then(function (res) {
                console.log(res.data);
                console.log("###res"+JSON.stringify(res));

                //把從json獲取的資料賦值給陣列

                self.tablePerson = res;
                console.log(self);
            }).fail(function () {
                console.log('失敗');
            })
        },

    });

    function changeRole(id) {
        var url="userManager";
        layer.open({
            type: 2,
            skin: 'layui-layer-lan',
            title: '角色管理',
            fix: false,
            shadeClose: false,
            maxmin: true,
            id:'selectUser',
            move: false,
            closeBtn:2,
            //以下程式碼為開啟視窗新增按鈕
            /* btn: ['確定', '取消'],
            btnAlign: 'c',
            yes: function(index, layero){
                /* //layer.closeAll();//關閉所有彈出層
                //var parentWin = layero.find('iframe')[0];
                var parentWin  = layer.getChildFrame('body', index);
                alert(parentWin);
                parentWin.contentWindow.doOk();
                //layer.close(index);//這塊是點選確定關閉這個彈出層
            }, */
            area: ['750px', '450px'],
            content: url,
            success: function (layero, index) {
                // 獲取子頁面的iframe
                var iframe = window['layui-layer-iframe' + index];
                // 向子頁面的全域性函式child傳參
                iframe.child(id);
            },
            end: function () {
                document.getElementById('groupName').value = "";
            }

        });

        //     console.log(id);
        // var codeurl = "/userInfo/userManager";
        // var data={"userid":id};
        // $.ajax({
        //     type: 'get',
        //     url: codeurl,
        //     data:data,
        //     async: false,
        //     contentType: 'application/json;charset=UTF-8',
        // }).then(function (res) {
        //     console.log(JSON.stringify(res.data));
        //     location.reload();
        //
        // }).fail(function () {
        //     console.log('失敗');
        // })
    }

    function allotRole(uid){
        var url="allotRole";
        layer.open({
            type: 2,
            skin: 'layui-layer-lan',
            title: '角色分配',
            fix: false,
            shadeClose: false,
            maxmin: true,
            id:'selectUser',
            move: false,
            closeBtn:2,
            //以下程式碼為開啟視窗新增按鈕
            /* btn: ['確定', '取消'],
            btnAlign: 'c',
            yes: function(index, layero){
                /* //layer.closeAll();//關閉所有彈出層
                //var parentWin = layero.find('iframe')[0];
                var parentWin  = layer.getChildFrame('body', index);
                alert(parentWin);
                parentWin.contentWindow.doOk();
                //layer.close(index);//這塊是點選確定關閉這個彈出層
            }, */
            area: ['750px', '450px'],
            content: url,
            success: function (layero, index) {
                // 獲取子頁面的iframe
                var iframe = window['layui-layer-iframe' + index];
                // 向子頁面的全域性函式child傳參
                iframe.child(uid);
            },
            end: function () {
                document.getElementById('groupName').value = "";
            }

        });

    }
</script>
</html>

 

這裡有一點需要注意的,程式知行到這裡的時候,一直報java.lang.IllegalStateException: Cannot call sendError() after the response has been committed這個錯誤,後來諮詢過大佬之後,大概明白了。

因為我的user實體中關聯著role實體,而role又關聯著user實體,所以在序列化實體的時候就會進入到死迴圈的狀態,

解決辦法就是在實體的get,set方法前加上@JsonBackReference註解。告訴程式不要級聯查詢,不過這樣做的問題就是,在序列化user實體的時候,不會返回role的值。

使用者管理controller

package com.example.controller;

import com.example.dao.UserInfoDao;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

@Controller
@RequestMapping("/userInfo")
public class UserInfoController {
@Autowired
    UserInfoDao userInfoDao;
    /**
     * 使用者查詢.
     * @return
     */
    @RequestMapping("/userList")
    @RequiresPermissions("userInfo:view")//許可權管理;
    public String userInfo(){
        return "userInfo";
    }

    /**
     * 使用者新增;
     * @return
     */
    @RequestMapping("/userAdd")
    @RequiresPermissions("userInfo:add")//許可權管理;
    public String userInfoAdd(){
        return "userInfoAdd";
    }

    /**
     * 使用者刪除;
     * @return
     */
    @RequestMapping("/userDel")
    @RequiresPermissions("userInfo:del")//許可權管理;
    public String userDel(){
        return "userInfoDel";
    }
    @RequestMapping("/userManager")
    @RequiresPermissions("userInfo:manager")//許可權管理;
    public String userManager(){
        return "userInfoManager";
    }

    /**
     * 獲取全部使用者資訊
     * @return
     */
    @RequestMapping(value="queryUser", method= RequestMethod.GET)
   // @RequiresPermissions("userInfo:queryUser")//許可權管理;
    @ResponseBody
    public List queryUser(){
        List list= userInfoDao.findAllUser();

        return list;
    }
    @RequestMapping(value="querypermission", method= RequestMethod.GET)
    // @RequiresPermissions("userInfo:queryUser")//許可權管理;
    public String queryPermission(){


        return "permissionman";
    }
    @RequestMapping(value="allotRole", method= RequestMethod.GET)
    // @RequiresPermissions("userInfo:queryUser")//許可權管理;
    public String allotRole(){


        return "allotRole";
    }


}

2.2使用者角色資源管理介面

新增使用者、刪除使用者、取消授權等操作在demo裡沒有寫,步驟就是增加使用者與角色對照表實體,角色與資源對照表實體,在取消授權或增加授權的時候,操作對照表實體,在資料庫中增加對應資料就可以了。

實現的時候將增加資源和角色的許可權控制起來,設定只有管理員或上級角色才可以增加刪除

下面是許可權控制的例子,可以通過類似的方法控制增加和刪除的許可權

@RequestMapping("/userManager")
    @RequiresPermissions("userInfo:manager")//只有使用者具有userInfo:manager 許可權的時候才可以訪問
                                            //可以修改為role:xxx 控制使用者是否能操作角色,
                                            //或xxx:xxx 控制對應的資源
    public String userManager(){
        return "userInfoManager";
    }

2.3介面