shiro(3)- 基于spring框架的Shiro配置(配置詳解)

shiro安全控制目錄

1. 導(dǎo)入依賴

    <properties>
        <shiro.version>1.2.3</shiro.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-web</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>${shiro.version}</version>
        </dependency>
    </dependencies>

2. web.xml配置

在web.xml中,將攔截器交由Spring管理。shiro(3)-Filter交由Spring管理-DelegatingFilterProxy。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
         version="3.0">
    <display-name>helloworld</display-name>
    <!-- 讀取spring配置文件 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:/spring/applicationContext.xml,
            classpath:/spring/application-shiro.xml,
            classpath:/spring/spring-mybatis.xml
        </param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>


    <!--攔截器由spring容器管理-->
    <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>/*</url-pattern>
    </filter-mapping>

    <!-- springMVC核心配置 -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:/spring/spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!-- 攔截設(shè)置 -->
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

注:設(shè)置targetFilterLifecycle=true的含義是保留Filter原有的init和destory方法的調(diào)用。

3. Spring配置文件

3.1 配置詳解

3.1.1. shiro主過濾器

[費(fèi)有特][陳][帶神你神子]

常用的權(quán)限控制:

  • anno:任何人都可以訪問;
  • authc:必須登錄之后才能訪問,不包括remember me(記住密碼);
  • user:登錄用戶才可以訪問,包含remember me(記住密碼);
  • perm:過濾[權(quán)限]規(guī)則,這個(gè)一般擴(kuò)展使用(使用自定義過濾器,從數(shù)據(jù)庫(kù)查詢用戶權(quán)限),不會(huì)使用原生的。
  • roles:過濾[角色]規(guī)則,這個(gè)一般擴(kuò)展使用,不會(huì)使用原生的。

攔截器優(yōu)先級(jí):
從上到下,從左到右,如果有匹配的攔截器就會(huì)阻斷并返回,例如訪問js/a.js,第一個(gè)攔截器anon符合,就返回true了,不在往下進(jìn)行匹配了。注意最后一個(gè)攔截最后一句是 /**=user意思就是除了上面的那些,其他的所有都要經(jīng)過。

    <!-- Shiro主過濾器本身功能十分強(qiáng)大,其強(qiáng)大之處就在于它支持任何基于URL路徑表達(dá)式的、自定義的過濾器的執(zhí)行 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!--shiro的核心安全接口,這是屬性是必須的-->
        <property name="securityManager" ref="securityManager"/>
        <!-- 要求登錄時(shí)的鏈接,非必須的屬性,默認(rèn)會(huì)自動(dòng)尋找Web工程根目錄下的"/login.jsp"頁(yè)面 -->
        <property name="loginUrl" value="/login/init"></property>
        <!-- 用戶訪問未對(duì)其授權(quán)的資源時(shí),所顯示的連接 -->
        <property name="unauthorizedUrl" value="/pages/error/403.jsp"/>
        <!--定義過濾器鏈-->
        <property name="filterChainDefinitions">
            <value>
                <!--Shiro過濾器鏈的配置-->
                /login/init/** = anon <!-- 對(duì)于登錄相關(guān)不進(jìn)行鑒權(quán) -->
                /static/** = anon <!-- 靜態(tài)資源不進(jìn)行鑒權(quán) -->
                /** = user
            </value>
        </property>
        <property name="filters">
            <map>
                <entry key="user" value-ref="userFilter"></entry>
            </map>
        </property>
    </bean>
    <!--自定義攔截器-->
    <bean id="userFilter" class="com.springmvc.common.filter.SystemUserFilter"/>

3.1.2. 配置securityManager

   <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <!--作用:授權(quán)認(rèn)證,此處為單個(gè)realm,若想配置多個(gè),可使用realms參數(shù)-->
        <property name="realm" ref="myRealm"/>
        <!--設(shè)置會(huì)話模式(已過期),需配置適當(dāng)?shù)腤ebSessionManager實(shí)例-->
        <property name="sessionMode" value="http"/>
        <!--建議關(guān)閉,配合/**=user使用時(shí),可未經(jīng)授權(quán)登錄系統(tǒng)-->
        <property name="rememberMeManager" ref="rememberMeManager"/>
        <!--配置會(huì)話管理器-->
        <property name="sessionManager" ref="defaultWebSessionManager"/>
    </bean>

DefaultWebSecurityManager類主要定義了設(shè)置subjectDao,獲取會(huì)話模式,設(shè)置會(huì)話模式,設(shè)置會(huì)話管理器,是否http會(huì)話模式等操作。

3.1.3 配置remeberManager

java shiro配置記住密碼功能 RememberMe功能怎么實(shí)現(xiàn)

Shiro的 rememberMe 功能使用指導(dǎo)(為什么rememberMe設(shè)置了沒作用?)

<!-- remenberMe配置 -->
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
  <constructor-arg value="rememberMe" />
  <!-- 瀏覽器中通過document.cookie可以獲取cookie屬性,設(shè)置了HttpOnly=true,在腳本中就不能的到cookie,可以避免cookie被盜用 -->
  <property name="httpOnly" value="true" />
  <!-- 默認(rèn)記住7天(單位:秒) -->
  <property name="maxAge" value="604800" />
</bean>
<!-- rememberMe管理器 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
  <property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}" />
  <property name="cookie" ref="rememberMeCookie" />
</bean>

注:Shiro主過濾器要使用/** = user。

3.1.4Realm配置

AuthorizingRealm為自定義Realm的父類,該類采用的模板方法模式,提供了2個(gè)方法供我們實(shí)現(xiàn)。
shiro(5)-有狀態(tài)認(rèn)證-Realm認(rèn)證的實(shí)現(xiàn)

  • Authentication [噢繁體kei神] 認(rèn)證;
  • Authorization [額死亂賊神] 授權(quán);
<bean id="myRealm" class="com.springmvc.common.shiro.UserAuthorizingRealm"></bean>

3.1.5 sessionManager配置

DefaultWebSessionManager類主要定義了session的創(chuàng)建,啟動(dòng),暫停與cookie的關(guān)聯(lián)定義。

<bean id="defaultWebSessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
        <!--全局session過期時(shí)間:30分鐘操作會(huì)覆蓋web.xml文件中的超時(shí)時(shí)間配置 -->
        <property name="globalSessionTimeout" value="1800000"/>
        <!---session保存到redis中-->
        <property name="sessionDAO" ref="customShiroSessionDAO"/>
        <!-- 所有的session一定要將id設(shè)置到Cookie之中,需要提供有Cookie的操作模版 -->
        <property name="sessionIdCookie" ref="simpleCookie"/>
        <!--定時(shí)掃描超時(shí)session-->
        <!-- session 監(jiān)聽,可以多個(gè)。 -->
        <property name="sessionListeners">
           <list>
               <ref bean="customSessionListener"/>
           </list>
         </property>
        <!--session關(guān)閉調(diào)度器-->
        <property name="sessionValidationScheduler" ref="sessionValidationScheduler"/>
         <!-- 需要讓此session可以使用該定時(shí)調(diào)度器進(jìn)行檢測(cè) -->
        <property name="sessionValidationSchedulerEnabled" value="true"/>
        <!--刪除過期的session-->
        <property name="deleteInvalidSessions" value="true"/>
    </bean>
    <!--自定義cookie的SessionId-->
    <bean id="simpleCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
        <constructor-arg index="0" value="JSESSIONID_COOKIE"/>
        <property name="httpOnly" value="true"/>
    </bean>
    <!--自定義session監(jiān)聽器-->
    <bean id="customSessionListener" class="om.springmvc.common.filter.CustomSessionListener">
        <property name="shiroSessionRepository" ref="jedisShiroSessionRepository"/>
    </bean>

自定義sessionListener:

public class CustomSessionListener implements SessionListener {
    public void onStart(Session session) {
        
    }

    public void onStop(Session session) {

    }

    public void onExpiration(Session session) {

    }
}

3. 代碼中的使用

@Controller
@RequestMapping("/login")
public class LoginAction {
    @RequestMapping(value = {"/init"})
    public ModelAndView init() {
        ModelAndView mv = new ModelAndView("login");
        return mv;
    }
    @RequestMapping("/login")
    public String login(@Param("username") String username,@Param("password") String password) {
        try {
            //創(chuàng)建token
            UsernamePasswordToken token = new UsernamePasswordToken();
            token.setUsername(username);
            token.setPassword(password.toCharArray());
            token.setRememberMe(true);
            //調(diào)用驗(yàn)證
            Subject subject = SecurityUtils.getSubject();
            subject.login(token);
            //驗(yàn)證是否登錄
            if(subject.isAuthenticated()){
                Session session=subject.getSession();
                //整合redis設(shè)置session超時(shí)時(shí)間setex(sessionId,30*60);
                //返回到頁(yè)面
                return "redirect:/user";
            }

        } catch (UnknownAccountException e) {
            //無(wú)用戶名
        }catch (LockedAccountException e){
            //密碼沒找到
        }catch (IncorrectCredentialsException e){
            //密碼不匹配
        }catch (AuthenticationException e){
            //其他登錄錯(cuò)誤
        }catch (Exception e){
            //未知異常
        }
        return "/error/403";
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容