springboot + jwt + shiro 前后端分離權限框架

權限類說明:

權限配置類:ShiroConfiguration (權限核心配置類)、AuthFilter(攔截器配置類)、AuthRealm(認證類)、AuthTokenVo、NoPermissionException(無權限異常處理類)、JWTUtil(token工具類)、AuthConstant(提示類)、ReturnMessage 返回信息類
測試需要的類:User UserController UserList UserPermission UserRole
maven坐標

權限核心配置

import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @ClassName ShiroConfiguration
 * @Description
 * @Author XinChunYu
 * @Date 2020/5/29 13:42
 * @Version 1.0
 **/
@Configuration
public class ShiroConfiguration {

    private org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(ShiroConfiguration.class);

    //從配置文件里面讀取是否需要啟動登錄認證的開關,默認true
    //@Value("${jwt.auth}")
    private boolean auth = true;

    //配置攔截器
    @Bean
    public ShiroFilterFactoryBean shiroFilter(org.apache.shiro.mgt.SecurityManager securityManager) {

        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //設置securityManager
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //啟用認證
        String openAuth = auth ? "auth" : "anon";

        //自定義過濾器鏈
        Map<String, javax.servlet.Filter> filters = new HashMap<>();
        //指定攔截器處理
        filters.put("auth", new com.lzqs.yuanzilian.shiro.AuthFilter());
        shiroFilterFactoryBean.setFilters(filters);
        Map<String, String> filterMap = new LinkedHashMap<>();

        //登錄請求不攔截
        filterMap.put("/user/login", "anon");
        //登錄頁面需要用到的接口,不攔截
        filterMap.put("/user/fetchCurrentUser", "anon");
        //攔截所有接口請求,做權限判斷
        filterMap.put("/**", openAuth);

        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
        logger.info("Shiro攔截器工廠類注入成功");
        return shiroFilterFactoryBean;
    }

    // SecurityManager 安全管理器;Shiro的核心
    @Bean
    public DefaultWebSecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm());
        return securityManager;
    }

    //自定義身份認證realm
    @Bean
    public AuthRealm userRealm() {
        return new AuthRealm();
    }

    @Bean("lifecycleBeanPostProcessor")
    //管理shiro生命周期
    public static LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    //Shiro注解支持
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(org.apache.shiro.mgt.SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager((org.apache.shiro.mgt.SecurityManager) securityManager);
        return authorizationAttributeSourceAdvisor;
    }

}

權限過濾器

package com.lzqs.yuanzilian.shiro;

import com.alibaba.fastjson.JSONObject;
import com.lzqs.yuanzilian.constant.ReturnMessage;
import com.lzqs.yuanzilian.shiro.util.AuthConstant;
import com.lzqs.yuanzilian.shiro.util.JWTUtil;
import io.micrometer.core.instrument.util.StringUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
import org.apache.shiro.web.util.WebUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @ClassName AuthFilter
 * @Description 實現自定義的認證攔截器,接收傳過來的token,實現前后端分離的權限認證
 * @Author XinChunYu
 * @Date 2020/5/29 14:03
 * @Version 1.0
 **/
public class AuthFilter extends AuthenticatingFilter {

    private org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(AuthorizingRealm.class);
    private ReturnMessage responseResult = ReturnMessage.failWithMsg(AuthConstant.AUTHENTICATE_FAIL);

        @Override
        protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
            return null;
        }

        /**
         * 在這里攔截所有請求
         * @param request
         * @param response
         * @param mappedValue
         * @return
         */
        @Override
        protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
            String token = JWTUtil.getRequestToken((HttpServletRequest)request);
            if (!StringUtils.isBlank(token)){
                try {
                    this.executeLogin(request, response);
                } catch (Exception e) {
                    // 應用異常
                    logger.info(e.getMessage());
                    responseResult = ReturnMessage.failWithMsg(e.getMessage());
                    return false;
                }
            } else {
                // cookie中未檢查到token或token為空
                HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
                String httpMethod = httpServletRequest.getMethod();
                String requestURI = httpServletRequest.getRequestURI();
                responseResult = ReturnMessage.failWithMsg(AuthConstant.TOKEN_BLANK);
                logger.info("請求 {} 的Token為空 請求類型 {}", requestURI, httpMethod);
                return false;
            }
            return true;
        }

        /**
         * 請求失敗攔截,請求終止,不進行轉發直接返回客戶端攔截結果
         * @param request
         * @param response
         * @return
         * @throws Exception
         */
        @Override
        protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception{
            HttpServletResponse httpServletResponse = (HttpServletResponse)response;
            httpServletResponse.setContentType("application/json; charset=utf-8");
            httpServletResponse.setCharacterEncoding("UTF-8");
            //ReturnMessage returnMessage = ReturnMessage.failWithMsg(AuthConstant.AUTHENTICATE_FAIL);
            httpServletResponse.getWriter().print(JSONObject.toJSONString(responseResult));
            return false;
        }

        /**
         * 用戶存在,執行登錄認證
         * @param request
         * @param response
         * @return
         * @throws Exception
         */
        @Override
        protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
            String token = JWTUtil.getRequestToken((HttpServletRequest)request);
            AuthTokenVo jwtToken = new AuthTokenVo(token);
            // 提交給AuthRealm進行登錄認證
            getSubject(request, response).login(jwtToken);
            return true;
        }
}

token認證和權限認證

import com.lzqs.yuanzilian.shiro.controller.User;
import com.lzqs.yuanzilian.shiro.controller.UserList;
import com.lzqs.yuanzilian.shiro.controller.UserPermission;
import com.lzqs.yuanzilian.shiro.controller.UserRole;
import com.lzqs.yuanzilian.shiro.util.AuthConstant;
import io.micrometer.core.instrument.util.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

/**
 * @ClassName AuthRealm
 * @Description
 * @Author XinChunYu
 * @Date 2020/5/29 13:51
 * @Version 1.0
 **/
public class AuthRealm extends AuthorizingRealm {

    private org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(AuthorizingRealm.class);

    /**
     * 重寫,繞過身份令牌異常導致的shiro報錯
     * @param authenticationToken
     * @return
     */
    @Override
    public boolean supports(AuthenticationToken authenticationToken){
        return authenticationToken instanceof AuthTokenVo;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        logger.info("用戶角色權限認證");
        //獲取用戶登錄信息
        User user = (User)principals.getPrimaryPrincipal();
        //添加角色和權限
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        for(UserRole userRole : user.getUserRoleList()){
            authorizationInfo.addRole(userRole.getUserRoleName());
            for(UserPermission permissionVo : userRole.getUserPermissionList()){
                authorizationInfo.addStringPermission(permissionVo.getUserPermissionName());
            }
        }
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        logger.info("執行認證邏輯");
        //獲得token
        String token = (String)authenticationToken.getCredentials();
        //獲得token中的用戶信息
        String username = JwtAuthenticator.getUsername(token);
        //判空
        if(StringUtils.isBlank(username)){
            throw new AuthenticationException(AuthConstant.TOKEN_BLANK);
        }
        User user = null;
        try{
            for(User u : UserList.userList){
                if(u.getUsername().equals(username)){
                    user = u;
                }
            }
            //查詢用戶是否存在
            if(user == null){
                throw new AuthenticationException(AuthConstant.TOKEN_INVALID);
                //token過期
            }else if(!(JwtAuthenticator.verifyToken(token, username, user.getPassword()))){
                throw new AuthenticationException(AuthConstant.TOKEN_EXPIRE);
            }
        }catch (Exception e){
            throw e;
        }
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user,
                token,
                getName());
        return authenticationInfo;
    }
}

jwt token對象

import org.apache.shiro.authc.AuthenticationToken;

/**
 * @ClassName AuthTokenVo
 * @Description
 * @Author XinChunYu
 * @Date 2020/5/29 14:09
 * @Version 1.0
 **/
public class AuthTokenVo implements AuthenticationToken {
    private String token;
    public AuthTokenVo(String token){
        this.token = token;
    }

    @Override
    public Object getPrincipal(){
        return token;
    }

    @Override
    public Object getCredentials(){
        return token;
    }
}

異常處理

import com.alibaba.fastjson.JSONObject;
import com.lzqs.yuanzilian.constant.ReturnMessage;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @ClassName NoPermissionException
 * @Description
 * @Author XinChunYu
 * @Date 2020/5/30 15:12
 * @Version 1.0
 **/
@ControllerAdvice
public class NoPermissionException {

    /**
     * 用戶角色權限認證 當沒有權限時會報UnauthorizedException異常 此處處理異常給前端返回提示語
     * @param response
     * @param ex
     * @throws IOException
     */
    @ResponseBody
    @ExceptionHandler(UnauthorizedException.class)
    public void handleShiroException(HttpServletResponse response, Exception ex) throws IOException {
        HttpServletResponse httpServletResponse = (HttpServletResponse)response;
        httpServletResponse.setContentType("application/json; charset=utf-8");
        httpServletResponse.setCharacterEncoding("UTF-8");
        //ReturnMessage returnMessage = ReturnMessage.failWithMsg(AuthConstant.AUTHENTICATE_FAIL);
        httpServletResponse.getWriter().print(JSONObject.toJSONString(ReturnMessage.failWithMsg("訪問了無權限目錄")));
    }
   //執行認證邏輯認證不通過時會走  過濾器AuthFilter中的onAccessDenied方法 所以這個異常不捕獲
   /* @ResponseBody
    @ExceptionHandler(AuthorizationException.class)
    public String AuthorizationException(Exception ex) {
        return "權限認證失敗";
    }*/
}

jwt token工具類

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.Date;

/**
 * @ClassName JWTUtil
 * @Description
 * @Author XinChunYu
 * @Date 2020/5/29 13:18
 * @Version 1.0
 **/
public class JWTUtil {

    // 過期時間50分鐘
    private static final long EXPIRE_TIME = 50*60*1000;

    /**
     * 校驗token是否正確
     * @param token 密鑰
     * @param secret 用戶的密碼
     * @return 是否正確
     */
    public static boolean verify(String token, String username, String secret) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withClaim("username", username)
                    .build();
            DecodedJWT jwt = verifier.verify(token);
            return true;
        } catch (Exception exception) {
            return false;
        }
    }

    /**
     * 獲得token中的信息無需secret解密也能獲得
     * @return token中包含的用戶名
     */
    public static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("username").asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    /**
     * 生成簽名,5min后過期
     * @param username 用戶名
     * @param secret 用戶的密碼
     * @return 加密的token
     */
    public static String sign(String username, String secret) {
        try {
            Date date = new Date(System.currentTimeMillis()+EXPIRE_TIME);
            Algorithm algorithm = Algorithm.HMAC256(secret);
            // 附帶username信息
            return JWT.create()
                    .withClaim("username", username)
                    .withExpiresAt(date)
                    .sign(algorithm);
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }

    public static String getRequestToken(HttpServletRequest request) {
        return request.getHeader("token");
    }
}

認證提示

package com.lzqs.yuanzilian.shiro.util;

/**
 * @ClassName AuthConstant
 * @Description 權限相關的常量
 * @Author XinChunYu
 * @Date 2020/5/29 14:06
 * @Version 1.0
 **/
public class AuthConstant {

        /**
         * cookie中存儲的token字段名
         */
        public final static String COOKIE_TOKEN_NAME = "Authorization";

        /**
         * token有效時間 時*分*秒*1000L
         */
        public final static Long EXPIRE_TIME = 3*60*1000L;//先設置3分鐘

        //登錄認證結果,返回給前端
        public final static String UNKNOWN_ACCOUNT = "登錄失敗, 用戶不存在。";

        public final static String WRONG_PASSWORD = "登錄失敗,密碼錯誤。";

        public final static String TOKEN_BLANK = "驗證失敗,token為空,請登錄。";

        public final static String TOKEN_INVALID = "驗證失敗,token錯誤。";

        public final static String TOKEN_EXPIRE = "驗證失敗,token過期,請重新登錄。";

        public final static String AUTHENTICATE_FAIL = "無訪問權限,請嘗試登錄或聯系管理員。";
}

ReturnMessage返回提示類

package com.lzqs.yuanzilian.constant;

import org.apache.commons.lang3.StringUtils;

import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * 通用的返回類
 **/
public class ReturnMessage implements Serializable {
    //狀態碼 100-成功,200-失敗 400-帶信息失敗
    private int code;
    //提示信息
    private String msg;
    //用戶要返回給瀏覽器的數據
    private Map<String, Object> data = new LinkedHashMap<>();

    public static ReturnMessage successWithData(Map<String, Object> data) {
        ReturnMessage result = new ReturnMessage();
        result.setCode(100);
        result.setMsg("成功");
        result.setData(data);
        return result;
    }

    public static ReturnMessage success() {
        ReturnMessage result = new ReturnMessage();
        result.setCode(100);
        result.setMsg("成功");
        return result;
    }

    public static ReturnMessage successWithMsg(String newmsg){
        ReturnMessage result = new ReturnMessage();
        result.setCode(100);
        result.setMsg(newmsg);
        return result;
    }

    public static ReturnMessage fail() {
        ReturnMessage result = new ReturnMessage();
        result.setCode(200);
        result.setMsg("系統錯誤");
        return result;
    }

    public static ReturnMessage failWithMsg(String newmsg) {
        ReturnMessage result = new ReturnMessage();
        result.setCode(400);
        result.setMsg(newmsg);
        return result;
    }


    /**
     * 失敗 + 自定義msg,缺省為"處理失敗"
     *
     * @param newmsg
     * @return
     */
    public static ReturnMessage failWithMsg(int code, String newmsg) {
        ReturnMessage result = new ReturnMessage();
        result.setCode(code);
        if (StringUtils.isEmpty(newmsg)) {
            newmsg = "處理失敗";
        }
        result.setMsg(newmsg);
        return result;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Map<String, Object> getData() {
        return data;
    }

    public void setData(Map<String, Object> data) {
        this.data = data;
    }

    public ReturnMessage add(String key, Object value) {
        this.getData().put(key, value);
        return this;
    }
}

controller控制器

import com.lzqs.yuanzilian.constant.ReturnMessage;
import com.lzqs.yuanzilian.shiro.util.AuthConstant;
import com.lzqs.yuanzilian.shiro.util.JWTUtil;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.util.Map;

/**
 * @ClassName UserController
 * @Description
 * @Author XinChunYu
 * @Date 2020/5/29 14:15
 * @Version 1.0
 **/
@Controller
@RequestMapping("/user")
public class UserController {


    @RequestMapping("/login")
    @ResponseBody
    public ReturnMessage login(@RequestBody Map<String, Object> map){
        String username = map.get("username").toString();
        String password = map.get("password").toString();
        User user = null;
        for(User u : UserList.userList){
            if(u.getUsername().equals(username)){
                user = u;
            }
        }
        if(user == null){
            //賬號不存在
            return ReturnMessage.failWithMsg(AuthConstant.UNKNOWN_ACCOUNT);
        }else if(!user.getPassword().equals(password)){
            //密碼錯誤
            return ReturnMessage.failWithMsg(AuthConstant.WRONG_PASSWORD);
        }else{
            //通過認證, 生成簽名
            String token = JWTUtil.sign(user.getUsername(), user.getPassword());
            return ReturnMessage.success().add("token", token);
        }
    }


    @RequiresPermissions("shop")
    @RequestMapping("/shop")
    @ResponseBody
    public ReturnMessage shop(@RequestBody Map<String, Object> map){

            return ReturnMessage.success();
    }

    @RequiresPermissions("order")
    @RequestMapping("/order")
    @ResponseBody
    public ReturnMessage order(@RequestBody Map<String, Object> map){

        return ReturnMessage.success();
    }

    /**
     * 不加@RequiresPermissions 注解時不會進行用戶授權認證
     * @param map
     * @return
     */
    @RequestMapping("/game")
    @ResponseBody
    public ReturnMessage game(@RequestBody Map<String, Object> map){
        return ReturnMessage.success();
    }

    @RequestMapping("/address")
    @ResponseBody
    public ReturnMessage address(@RequestBody Map<String, Object> map){
        return ReturnMessage.success();
    }
}

用戶類

package com.lzqs.yuanzilian.shiro.controller;

import java.util.List;

/**
 * @ClassName UserBean
 * @Description 用戶表
 * @Author XinChunYu
 * @Date 2020/5/29 13:16
 * @Version 1.0
 **/
public class User {
    private Long userId;
    private String username;
    private String password;
    private String salt;//鹽值
    private List<UserRole> userRoleList;

    public User() {
    }

    public User(Long userId, String username, String password, String salt, List<UserRole> userRoleList) {
        this.userId = userId;
        this.username = username;
        this.password = password;
        this.salt = salt;
        this.userRoleList = userRoleList;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public List<UserRole> getUserRoleList() {
        return userRoleList;
    }

    public void setUserRoleList(List<UserRole> userRoleList) {
        this.userRoleList = userRoleList;
    }

    public String getSalt() {
        return salt;
    }

    public void setSalt(String salt) {
        this.salt = salt;
    }
}

角色類

package com.lzqs.yuanzilian.shiro.controller;

import java.util.List;

/**
 * @ClassName UserRole
 * @Description 角色表
 * @Author XinChunYu
 * @Date 2020/5/29 13:34
 * @Version 1.0
 **/
public class UserRole {
    private Long userRoleId;
    private String userRoleName;
    List<UserPermission> userPermissionList;

    public UserRole(Long userRoleId, String userRoleName, List userPermissionList) {
        this.userRoleId = userRoleId;
        this.userRoleName = userRoleName;
        this.userPermissionList = userPermissionList;
    }

    public Long getUserRoleId() {
        return userRoleId;
    }

    public void setUserRoleId(Long userRoleId) {
        this.userRoleId = userRoleId;
    }

    public String getUserRoleName() {
        return userRoleName;
    }

    public void setUserRoleName(String userRoleName) {
        this.userRoleName = userRoleName;
    }

    public List<UserPermission> getUserPermissionList() {
        return userPermissionList;
    }

    public void setUserPermissionList(List<UserPermission> userPermissionList) {
        this.userPermissionList = userPermissionList;
    }
}

權限

package com.lzqs.yuanzilian.shiro.controller;

/**
 * @ClassName Permission
 * @Description 權限表
 * @Author XinChunYu
 * @Date 2020/5/29 13:35
 * @Version 1.0
 **/
public class UserPermission {
    private Long userPermissionId;
    private String userPermissionName;

    public UserPermission(Long userPermissionId, String userPermissionName) {
        this.userPermissionId = userPermissionId;
        this.userPermissionName = userPermissionName;
    }

    public Long getUserPermissionId() {
        return userPermissionId;
    }

    public void setUserPermissionId(Long userPermissionId) {
        this.userPermissionId = userPermissionId;
    }

    public String getUserPermissionName() {
        return userPermissionName;
    }

    public void setUserPermissionName(String userPermissionName) {
        this.userPermissionName = userPermissionName;
    }
}

用戶集合在這就不建表查數據庫了

package com.lzqs.yuanzilian.shiro.controller;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName UserList
 * @Description
 * @Author XinChunYu
 * @Date 2020/5/29 16:15
 * @Version 1.0
 **/
public class UserList {

    public static List<User> userList = new ArrayList<>();
    static{
        ArrayList<UserPermission> userPermissionArrayList1 = new ArrayList<>();
        userPermissionArrayList1.add(new UserPermission(1l,"shop"));
        userPermissionArrayList1.add(new UserPermission(2l,"game"));
        userPermissionArrayList1.add(new UserPermission(1l,"order"));
        userPermissionArrayList1.add(new UserPermission(1l,"address"));
        ArrayList<UserRole> userRoleArrayList1 = new ArrayList<>();
        userRoleArrayList1.add(new UserRole(1L, "老板", userPermissionArrayList1));
        User user1 = new User(1l, "admin", "123456", "iwejfiwjf", userRoleArrayList1);

        ArrayList<UserPermission> userPermissionArrayList2 = new ArrayList<>();
        userPermissionArrayList2.add(new UserPermission(1l,"shop"));
        userPermissionArrayList2.add(new UserPermission(2l,"game"));
        ArrayList<UserRole> userRoleArrayList2 = new ArrayList<>();
        userRoleArrayList2.add(new UserRole(2L, "經理", userPermissionArrayList2));
        User user2 = new User(2l, "xiaoming", "123456", "jfiosjfos", userRoleArrayList2);

        userList.add(user1);
        userList.add(user2);
    }
}

maven坐標

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.7.0</version>
        </dependency>
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,362評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,013評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,346評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,421評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,146評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,534評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,585評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,767評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,318評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,074評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,258評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,828評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,486評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,916評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,156評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,993評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,234評論 2 375