通過前10篇文章,咱們已經能夠快速搭建一個springboot的web項目;前端
今天,咱們在上一節基礎上繼續集成shiro框架,實現一個能夠通用的後臺管理系統;包括用戶管理,角色管理,菜單管理三大系統經常使用管理模塊;java
要想實現用戶管理+角色管理+菜單管理三大模塊,基本上咱們經常使用的解決方案就是以下五個表(sql腳本在最後):mysql
1.添加pom依賴。git
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.4.0</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
2.編輯shiro配置類:ShiroConfig.javagithub
package com.zjt.config; import com.zjt.realm.MyRealm; import org.apache.shiro.mgt.SecurityManager; 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.CookieRememberMeManager; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.servlet.SimpleCookie; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; import java.util.Map; /** * @Author: Zhaojiatao * @Description: Shiro配置類 * @Date: Created in 2018/2/8 13:29 * @param */ @Configuration public class ShiroConfig { /** * ShiroFilterFactoryBean 處理攔截資源文件問題。 * 注意:單獨一個ShiroFilterFactoryBean配置是或報錯的,覺得在 * 初始化ShiroFilterFactoryBean的時候須要注入:SecurityManager * * Filter Chain定義說明 一、一個URL能夠配置多個Filter,使用逗號分隔 二、當設置多個過濾器時,所有驗證經過,才視爲經過 * 三、部分過濾器可指定參數,如perms,roles * */ @Bean public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); // 必須設置 SecurityManager shiroFilterFactoryBean.setSecurityManager(securityManager); // 若是不設置默認會自動尋找Web工程根目錄下的"/login.jsp"頁面 //shiroFilterFactoryBean.setLoginUrl("/login.ftl"); //配置退出過濾器,其中的具體的退出代碼Shiro已經替咱們實現了 shiroFilterFactoryBean.setLoginUrl("/tologin"); shiroFilterFactoryBean.setUnauthorizedUrl("/tologin"); // 攔截器. Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); //配置記住我或認證經過能夠訪問的地址(配置不會被攔截的連接 順序判斷) filterChainDefinitionMap.put("/static/**", "anon"); filterChainDefinitionMap.put("/user/login", "anon"); filterChainDefinitionMap.put("/drawImage", "anon"); // 配置退出過濾器,其中的具體的退出代碼Shiro已經替咱們實現了 filterChainDefinitionMap.put("/admin/user/logout", "logout"); // <!-- 過濾鏈定義,從上向下順序執行,通常將 /**放在最爲下邊 -->:這是一個坑呢,一不當心代碼就很差使了; // <!-- authc:全部url都必須認證經過才能夠訪問; anon:全部url都均可以匿名訪問--> filterChainDefinitionMap.put("/**", "authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public SecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); // 設置realm. securityManager.setRealm(myRealm()); //注入記住我管理器; securityManager.setRememberMeManager(rememberMeManager()); return securityManager; } /** * 身份認證realm; (這個須要本身寫,帳號密碼校驗;權限等) * * @return */ @Bean public MyRealm myRealm() { MyRealm myRealm = new MyRealm(); return myRealm; } /** * Shiro生命週期處理器 * @return */ @Bean public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){ return new LifecycleBeanPostProcessor(); } /** * 開啓Shiro的註解(如@RequiresRoles,@RequiresPermissions),需藉助SpringAOP掃描使用Shiro註解的類,並在必要時進行安全邏輯驗證 * 配置如下兩個bean(DefaultAdvisorAutoProxyCreator(可選)和AuthorizationAttributeSourceAdvisor)便可實現此功能 * 不要使用 DefaultAdvisorAutoProxyCreator 會出現二次代理的問題,這裏不詳述 * @return */ /* @Bean @DependsOn({"lifecycleBeanPostProcessor"}) public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){ DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator(); advisorAutoProxyCreator.setProxyTargetClass(true); return advisorAutoProxyCreator; }*/ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){ AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); authorizationAttributeSourceAdvisor.setSecurityManager(securityManager()); return authorizationAttributeSourceAdvisor; } /** * cookie對象; * 記住密碼實現起來也是比較簡單的,主要看下是如何實現的。 * @return */ @Bean public SimpleCookie rememberMeCookie(){ System.out.println("ShiroConfiguration.rememberMeCookie()"); //這個參數是cookie的名稱,對應前端的checkbox的name = rememberMe SimpleCookie simpleCookie = new SimpleCookie("rememberMe"); //<!-- 記住我cookie生效時間30天 ,單位秒;--> simpleCookie.setMaxAge(259200); return simpleCookie; } /** * cookie管理對象; * @return */ @Bean public CookieRememberMeManager rememberMeManager(){ System.out.println("ShiroConfiguration.rememberMeManager()"); CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager(); cookieRememberMeManager.setCookie(rememberMeCookie()); return cookieRememberMeManager; } }
3.實現自定義MyRealm.javaweb
package com.zjt.realm; import com.zjt.entity.Tmenu; import com.zjt.entity.Trole; import com.zjt.entity.Tuser; import com.zjt.mapper.TmenuMapper; import com.zjt.mapper.TroleMapper; import com.zjt.mapper.TuserMapper; import com.zjt.mapper.TuserroleMapper; import org.apache.shiro.SecurityUtils; 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; import tk.mybatis.mapper.entity.Example; import javax.annotation.Resource; import java.util.HashSet; import java.util.List; import java.util.Set; /** * 自定義Realm * @author zjt * */ public class MyRealm extends AuthorizingRealm{ @Resource private TuserMapper tuserMapper; @Resource private TroleMapper troleMapper; @Resource private TuserroleMapper tuserroleMapper; @Resource private TmenuMapper tmenuMapper; /** * 受權 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { String userName=(String) SecurityUtils.getSubject().getPrincipal(); //User user=userRepository.findByUserName(userName); //根據用戶名查詢出用戶記錄 Example tuserExample=new Example(Tuser.class); tuserExample.or().andEqualTo("userName",userName); Tuser user=tuserMapper.selectByExample(tuserExample).get(0); SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(); //List<Role> roleList=roleRepository.findByUserId(user.getId()); List<Trole> roleList = troleMapper.selectRolesByUserId(user.getId()); Set<String> roles=new HashSet<String>(); if(roleList.size()>0){ for(Trole role:roleList){ roles.add(role.getName()); //List<Tmenu> menuList=menuRepository.findByRoleId(role.getId()); //根據角色id查詢全部資源 List<Tmenu> menuList=tmenuMapper.selectMenusByRoleId(role.getId()); for(Tmenu menu:menuList){ info.addStringPermission(menu.getName()); // 添加權限 } } } info.setRoles(roles); return info; } /** * 權限認證 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String userName=(String)token.getPrincipal(); //User user=userRepository.findByUserName(userName); Example tuserExample=new Example(Tuser.class); tuserExample.or().andEqualTo("userName",userName); Tuser user=tuserMapper.selectByExample(tuserExample).get(0); if(user!=null){ AuthenticationInfo authcInfo=new SimpleAuthenticationInfo(user.getUserName(),user.getPassword(),"xxx"); return authcInfo; }else{ return null; } } }
4.登陸、退出、權限限制spring
登陸:subject.login(token);sql
退出:SecurityUtils.getSubject().logout();數據庫
在方法前使用shiro註解實現權限校驗,如:@RequiresPermissions(value = {"用戶管理"}) 表示當前用戶必須擁有用戶管理的權限;apache
一、登陸
請求http://localhost:8080/blogmanager/
被shiro攔截後自動跳轉到登陸界面;
項目地址能夠在配置文件中配置:
源碼:src\main\resources\templates\login.ftl
用戶名:admin
密碼:1
二、系統管理-菜單管理
菜單管理頁面源碼:src\main\resources\templates\power\menu.ftl
裏面使用了ztree實現的菜單的新建、編輯、刪除;
菜單管理的後臺接口:com.zjt.web.MenuController.java
注意一級菜單在頂部顯示,且一級菜單名不可爲純數字;
二級三級菜單在左側顯示,且最多隻能到三級菜單;
三、系統管理-角色管理
src\main\resources\templates\power\role.ftl
com.zjt.web.RoleAdminController.java
頁面使用了jqgrid表格插件;
並能夠設置每一個角色對應的菜單權限:
四、系統管理-用戶管理
src\main\resources\templates\power\user.ftl
com.zjt.web.UserAdminController.java
選擇行後能夠設置角色:
本後臺管理系統可做爲通用的後臺管理系統,她簡單純淨;內置完善的菜單管理+角色管理+用戶管理;拿來即用;
使用技術涉及:
springboot+springmvc+mysql+mybatis+通用mapper+分頁插件+shiro+freemarker+layui+ztree
其中layui模板使用的是layuicms2.0
本項目源碼:
https://github.com/zhaojiatao/springboot-zjt-chapter10-springboot-mysql-mybatis-shiro-freemarker-layui.git
sql腳本含在項目sql文件夾中
項目訪問地址和端口在配置文件中:application-dev.properties