SSM整合shiro 實現用戶角色權限管理

ps:

一.環境:SpringMvc+spring+Mybatis,前後端分離,只支持單臺項目(未實現單點登入);

二.需對shiro原理流程,有基礎的理解,以及用戶權限需求的應用場景明瞭,能更好項目整合;

三.shiro的基本構成:

    1.Subject (接口) : 主體(當前用戶) 定義了認證授權的相關函數,通過SecurityManage 安全管理器進行授權按認證
    2.SecurityManage (接口)  : 框架核心核心 安全管理器,對subject進行認證,授權
        3.Authenticator : 認證器,對主體進行認證(登入)
        4.Authorizer : 授權器,通過認證後,在訪問功能接口時,通過授權器判斷用戶是否有該功能的操作權限
        5.Realm : 讀取用戶權限數據, 進行安全認證需要通過realm,獲取用戶權限數據
    6.SessionManage : 會話管理器,自定義了一套,不依賴http的session
    7.SessionDAO : 操作會話信息,例如將會話信息存儲到redis庫
        8.CacheManage : 緩存管理器 ,將用戶權限數據存儲在緩存
    9.Cryptography : 加密

demo

1.maven依賴:

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-ehcache</artifactId>
    <version>1.4.1</version>
</dependency>
<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.8.0</version>
</dependency>
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.4.1</version>
</dependency>

2.spring整合shiro配置:

1)spring.xml
<!--自定義的relam-->
<bean name="shiroRealm" class="hotkidclub.shiro.ShiroRealm"/>
<!--緩存管理器-->
<bean name="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"/>
<!--shiro安全管理器-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="realm" ref="shiroRealm"/>
    <property name="cacheManager" ref="shiroCacheManager"/>
</bean>
<!-- 啓動安全管理器: 相當於調用SecurityUtils.setSecurityManager(securityManager) -->
<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager"/>
    <property name="arguments" ref="securityManager"/>
</bean>
<!-- shiro 的Web過濾器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
    <property name="securityManager" ref="securityManager"/>
    <!--如果沒有認證將要跳轉的登陸地址 -->
    <property name="loginUrl" value="/login"/>
    <!-- 配置安全規則:1). anon 可以被匿名訪問
                  2). authc 必須認證(即登錄)後纔可能訪問的頁面 -->
    <property name="filterChainDefinitions">
        <value>
            <!-- 登錄不攔截 -->
            / = anon
            /static/** = anon
            /login.ctrl = anon
            /** = authc
        </value>
    </property>
</bean>
<!-- AOP式方法級權限檢查  -->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor">
    <property name="proxyTargetClass" value="true"/>
</bean>
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    <property name="securityManager" ref="securityManager"/>
</bean>
<!-- Shiro生命週期處理器-->
<bean name="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

2)web.xml

<!-- shiro過慮器 -->
<filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
        <param-name>targetFilterLifecycle</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>shiroFilter</filter-name>
    <url-pattern>*.ctrl</url-pattern>
</filter-mapping>
<!-- 接收接口請求適配器 -->
<servlet>
    <servlet-name>backend_shiro_demo</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value></param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>backend_shiro_demo</servlet-name>
    <url-pattern>*.ctrl</url-pattern>
</servlet-mapping>

3).自定義shiro的realm

 

package hotkidclub.shiro;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;

public class ShiroRealm extends AuthorizingRealm {

   /**
    * 認證器 :
    * <p>
    * 本平臺用戶登入接口調用-subject.login() : 回調該函數
    * </p>
    * 
    * @param authcToken 憑證信息:可存放用戶賬號密碼
    * @return 認證信息:包含當前請求登入的用戶信息
    * @throws AuthenticationException
    */
   @Override
   protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
      System.out.println("認證開始");
      Subject subject = SecurityUtils.getSubject();
      // 1.獲取認證的主體信息:賬戶密碼...,TODO authcToken轉換爲本平臺業務bean
      UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
      // 2.對比數據庫存儲的賬號密碼
      // 3.創建簡單認證信息對象 : new SimpleAuthenticationInfo(object, object, 字符串);可傳遞自定義對象,字符內容;
      Session session = subject.getSession();
      session.setAttribute("user", token.getPrincipal());
      SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(token.getPrincipal(), token.getCredentials(), getName());
      return info;
   }

   /**
    * 授權器 : 校驗用戶的角色和權限
    * <p>
    * 本平臺接口配置角色/權限的授權註解時 : 回調該函數
    * </p>
    * 
    * @param principalCollection
    * @return
    */
   @Override
   protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
      // TODO 1.通過用戶名去數據庫查詢該用戶有哪些角色和權限
      // TODO 2.設置角色信息
      // TODO 3.設置權限信息
      // 創建簡單授權信息對象
      SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
      info.addRole("admin");
      info.addStringPermission("add");
      System.out.println("鑑權完成");
      return info;
   }
}

 

3.測試

 

    //登入

    @ResponseBody
    @PostMapping(value = "/login.ctrl", produces = "application/json")
    public Map<String, Object> login(@RequestBody Map<String, Object> params, HttpSession httpSession) {
        Object object = null;
            // shiro login
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(賬號,密碼 );
            subject.login(token);
            object = result;
        
        return object;
    }
    
    
    /**
     * 測試:角色/權限的核查
     *
     * @param session
     * @return
     */
    @ResponseBody
    @RequiresRoles(value = "admin")//鑑查角色註解
    @RequiresPermissions(value = "add")//鑑權註解
    @GetMapping(value = "/check.ctrl", produces = "application/json") // @RequiresPermissions (value={"add", "update"}, logical= Logical.OR)
    public Map<String, Object> permission(HttpSession session) {
        String object = null;try {
            Subject subject = SecurityUtils.getSubject();
            object = "ok";
        }
        return object;
    }

 

 

 

 

 

 

 

發佈了25 篇原創文章 · 獲贊 11 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章