麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

Java 權限框架 Shiro 實戰二:與spring集成、filter機制

2019-11-15 00:45:31
字體:
來源:轉載
供稿:網友
java 權限框架 Shiro 實戰二:與sPRing集成、filter機制

Shiro和Spring的集成,涉及到很多相關的配置,涉及到shiro的filer機制以及它擁有的各種默認filter,涉及到shiro的權限判斷標簽,權限注解,涉及到session管理等等方面。

1. 配置

首先需要在web.xml中專門負責接入shiro的filter:

    <!-- shiro 安全過濾器 -->    <filter>        <filter-name>shiroFilter</filter-name>        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>        <async-supported>true</async-supported>        <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>

并且需要放在所有filter中靠前的位置,比如需要放在siteMesh的過濾器之前。

DelegatingFilterProxy 表示這是一個代理filter,它會將實際的工作,交給spring配置文件中 id="shiroFilter" 的bean來處理:

public class DelegatingFilterProxy extends GenericFilterBean {    private String contextAttribute;    private WebapplicationContext webApplicationContext;    private String targetBeanName;    private boolean targetFilterLifecycle = false;    private volatile Filter delegate;    private final Object delegateMonitor = new Object();    @Override    protected void initFilterBean() throws ServletException {        synchronized (this.delegateMonitor) {            if (this.delegate == null) {                // If no target bean name specified, use filter name.                if (this.targetBeanName == null) {                    this.targetBeanName = getFilterName();                }                // Fetch Spring root application context and initialize the delegate early,                // if possible. If the root application context will be started after this                // filter proxy, we'll have to resort to lazy initialization.                WebApplicationContext wac = findWebApplicationContext();                if (wac != null) {                    this.delegate = initDelegate(wac);                }            }        }    }
public abstract class GenericFilterBean implements        Filter, BeanNameAware, EnvironmentAware, ServletContextAware, InitializingBean, DisposableBean {    @Override    public final void init(FilterConfig filterConfig) throws ServletException {        Assert.notNull(filterConfig, "FilterConfig must not be null");        if (logger.isDebugEnabled()) {            logger.debug("Initializing filter '" + filterConfig.getFilterName() + "'");        }        this.filterConfig = filterConfig;        // Set bean properties from init parameters.        try {            PropertyValues pvs = new FilterConfigPropertyValues(filterConfig, this.requiredProperties);            BeanWrapper bw = PropertyaccessorFactory.forBeanPropertyAccess(this);            ResourceLoader resourceLoader = new ServletContextResourceLoader(filterConfig.getServletContext());            bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, this.environment));            initBeanWrapper(bw);            bw.setPropertyValues(pvs, true);        }        catch (BeansException ex) {            String msg = "Failed to set bean properties on filter '" +                filterConfig.getFilterName() + "': " + ex.getMessage();            logger.error(msg, ex);            throw new NestedServletException(msg, ex);        }        // Let subclasses do whatever initialization they like.        initFilterBean();        if (logger.isDebugEnabled()) {            logger.debug("Filter '" + filterConfig.getFilterName() + "' configured successfully");        }    }

// Let subclasses do whatever initialization they like.

initFilterBean();

Filter 接口的 init 方法調用 initFilterBean(), 而該方法在子類中進行實現,它先獲得 this.targetBeanName = getFilterName(); bean的名稱,也就是id,然后對其進行初始化:this.delegate = initDelegate(wac); 其實就是從bean工廠中根據bean的名稱找到bean.

    protected Filter initDelegate(WebApplicationContext wac) throws ServletException {        Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);        if (isTargetFilterLifecycle()) {            delegate.init(getFilterConfig());        }        return delegate;    }

而 shiroFilter在spring中的配置如下:

    <!-- Shiro的Web過濾器 -->    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">        <property name="securityManager" ref="securityManager"/>        <property name="loginUrl" value="/login"/>        <property name="successUrl" value="/"/>        <property name="unauthorizedUrl" value="/unauthorized"/>        <property name="filters">            <util:map>                <entry key="authc" value-ref="passThruAuthenticationFilter"/>            </util:map>        </property>        <property name="filterChainDefinitions">            <value>                /reg/** = anon    <!-- 注冊相關  -->                /login = authc                /logout = logout                /authenticated = authc                /loginController = anon                /js/** = anon                  /CSS/** = anon                   /img/** = anon                  /html/** = anon                /font-awesome/** = anon             <!-- /** = anon                 /user/modifyPassWord = perms["user:update", "user:select"]           -->                /** = user            </value>        </property>    </bean>

上面的shiroFilter的配置又引出了 securityManager 和 shiro 的filter機制和他自帶的一些filter.

2. securityManager 級相關配置

在上一篇文章 Java 權限框架 Shiro 實戰一:理論基礎 中我們知道securityManager是shiro的頂層對象,它管理和調用其它所有子系統,負責系統的安全。我們知道shiro有兩個類型的securityManager一個是JavaSE環境,默認是DefaultSecurityManager一個是web環境,默認是DefaultWebSecurityManager。所以我們web環境肯定應該使用后者。我們從頂層對象一層一層向下配置。先看securityManager如何配置:

    <!-- 相當于調用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>

上面的配置相當于調用SecurityUtils.setSecurityManager(securityManager) ,來注入了下面配置的 securityManager(DefaultWebSecurityManager) :

    <!-- 安全管理器 -->    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">        <property name="realm" ref="userRealm"/>        <property name="cacheManager" ref="cacheManager"/>        <property name="rememberMeManager" ref="rememberMeManager"/>    </bean>

它默認使用的session管理器是 ServletContainerSessionManager,所以上面沒有配置,所以就使用默認值。配置了就會覆蓋下面的默認值:

    public DefaultWebSecurityManager() {        super();        ((DefaultSubjectDAO) this.subjectDAO).setSessionStorageEvaluator(new DefaultWebSessionStorageEvaluator());        this.sessionMode = HTTP_SESSION_MODE;        setSubjectFactory(new DefaultWebSubjectFactory());        setRememberMeManager(new CookieRememberMeManager());        setSessionManager(new ServletContainerSessionManager());    }

顯然 securityManager 最重要的工作就是用戶登錄認證和獲得用戶的權限等相關信息,所以 realm 是其最重要的依賴:

    <!-- Realm實現 -->    <bean id="userRealm" class="com.ems.shiro.UserRealm">        <property name="credentialsMatcher" ref="credentialsMatcher"/>        <property name="cachingEnabled" value="false"/>    </bean>

要理解上面userRealm的配置,就的先理解 UserRealm 的繼承體系:

UserRealm 繼承 AuthorizingRealm 顯然是為了獲取權限信息,對用戶進行訪問控制;繼承AuthenticatingRealm顯然是為了獲得用戶的認證信息,對用戶進行認證。而 credentialsMatcher 就是 AuthenticatingRealm 使用來進行密碼驗證的依賴的組件

public abstract class AuthenticatingRealm extends CachingRealm implements Initializable {/**     * Credentials matcher used to determine if the provided credentials match the credentials stored in the data store.     */    private CredentialsMatcher credentialsMatcher;

再看其credentialsMatcher bean的配置:

    <!-- 憑證匹配器(驗證登錄密碼是否正確) -->    <bean id="credentialsMatcher" class="com.ems.shiro.RetryLimitHashedCredentialsMatcher">        <constructor-arg ref="cacheManager"/>        <property name="hashAlgorithmName" value="SHA-256"/>        <property name="hashIterations" value="2"/>        <property name="storedCredentialsHexEncoded" value="true"/>    </bean>

配置就是 hash加密的相關參數:hash算法,hash迭代次數等。到這里 shiro 登錄驗證的配置就完了。至于獲取用戶信息和用戶的權限的信息,都在userRealm中實現了:

public class UserRealm extends AuthorizingRealm {    @Autowired    private UserService userService;    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {        String userName = (String)principals.getPrimaryPrincipal();        User user = userService.getUserByUserName (userName );        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();        authorizationInfo.setRoles(userService.findRolesByUserId(user.getId()));        authorizationInfo.setStringPermissions(userService.findPermissionsByUserId(user.getId()));        return authorizationInfo;    }        @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {        String userName = (String)token.getPrincipal();        User user = userService.getUserByUserName(userName);        if(user == null) {            throw new UnknownAccountException();//沒找到賬戶        }        if(user.getLocked() == 0) {            throw new LockedAccountException(); //帳號鎖定        }        if(user.getLocked() == 2){            throw new AuthenticationException("account was inactive");        }        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(                user.getUserName(),                user.getPassword(), // 密碼                ByteSource.Util.bytes(user.getCredentialsSalt()),    // salt                getName()  // realm name        );                return authenticationInfo;    }

securityManager會在需要的時候回調上面 的 doGetAuthorizationInfo 和 doGetAuthenticationInfo 方法,從realm中獲得登錄認證信息和用戶權限信息。至于 rememberMeManager 主要是實現使用cookie表示我已經登錄過了,下次不需要重新登錄,這一個功能,也就是“記住我”登錄過這一功能:

    <!-- rememberMe管理器 -->    <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">        <!-- rememberMe cookie加密的密鑰 建議每個項目都不一樣 默認AES算法 密鑰長度(128 256 512 位)-->        <property name="cipherKey"                  value="#{T(org.apache.shiro.codec.Base64).decode('9FvVhtFLUs0KnA3Kprsdyg==')}"/>        <property name="cookie" ref="rememberMeCookie"/>    </bean>    <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">        <constructor-arg value="rememberMe"/>        <property name="httpOnly" value="true"/>        <property name="maxAge" value="2592000"/><!-- 30天 -->    </bean>

還有cacheManager的配置:

    <!--ehcache-->    <bean id="ehcacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">        <property name="configLocation" value="classpath:ehcache/ehcache.xml"/>    </bean>    <bean id="springCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">        <property name="cacheManager" ref="ehcacheManager"/>    </bean>    <!-- 緩存管理器 -->    <bean id="cacheManager" class="com.ems.shiro.SpringCacheManagerWrapper">        <property name="cacheManager" ref="springCacheManager"/>    </bean>

使用的是 EhCache.

3. Shiro 的filter機制和自帶的filter

Shiro的filter是基于Servlet的Filter接口實現的。我們通過Shiro提供的form登錄filter:FormAuthenticationFilter 和 ShiroFilter 看看其實現:

繼承中的每一層都實現了一些功能:

1> NameableFilter:實現給filter取名的功能(Allows a filter to be named via JavaBeans-compatible)

/** * Allows a filter to be named via JavaBeans-compatible*/public abstract class NameableFilter extends AbstractFilter implements Nameable {    /**     * The name of this filter, unique within an application.     */    private String name;

2> OncePerRequestFilter : 保證對于同一個request,fiter只執行一次(Filter base class that guarantees to be just executed once per request)

/** * Filter base class that guarantees to be just executed once per request, * on any servlet container. It provides a {@link #doFilterInternal} * method with HttpServletRequest and HttpServletResponse arguments.*/public abstract class OncePerRequestFilter extends NameableFilter {

3> AdviceFilter: SpringMVC風格的過濾器(就是preHandle, postHandle,afterCompletion 三接口的過濾器)

 /*** A Servlet Filter that enables AOP-style &quot;around&quot; advice for a ServletRequest via * preHandle(javax.servlet.ServletRequest, javax.servlet.ServletResponse),* postHandle(javax.servlet.ServletRequest, javax.servlet.ServletResponse),* and afterCompletion(javax.servlet.ServletRequest, javax.servlet.ServletResponse, Exception)hooks.*/public abstract class AdviceFilter extends OncePerRequestFilter {    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {        return true;    }    @SuppressWarnings({"UnusedDeclaration"})    protected void postHandle(ServletRequest request, ServletResponse response) throws Exception {    }    @SuppressWarnings({"UnusedDeclaration"})    public void afterCompletion(ServletRequest request, ServletResponse response, Exception exception) throws Exception {    }

4> PathMatchingFilter:該過濾器僅僅處理指定的路徑(比如上面的配置:/js/** = anon,表示對 /js/ 目錄和其子目錄的請求,交給anon過濾器處理)

/** * <p>Base class for Filters that will process only specified paths and allow all others to pass through.</p>*/public abstract class PathMatchingFilter extends AdviceFilter implements PathConfigProcessor {

5> AccessControlFilter: 實現提供對資源的訪問控制,沒有權限時,重定向到登錄頁面,登錄之后跳轉到原來的那個頁面

/** * Superclass for any filter that controls access to a resource and may redirect the user to the login page * if they are not authenticated.  This superclass provides the method * saveRequestAndRedirectToLogin(javax.servlet.ServletRequest, javax.servlet.ServletResponse) * which is used by many subclasses as the behavior when a user is unauthenticated.*/public abstract class AccessControlFilter extends PathMatchingFilter {

6> AuthenticationFilter: 實現對訪問用戶的認證要求,也就是必須登錄了才能訪問

/** * Base class for all Filters that require the current user to be authenticated. This class encapsulates the * logic of checking whether a user is already authenticated in the system while subclasses are required to perform * specific logic for unauthenticated requests.*/public abstract class AuthenticationFilter extends AccessControlFilter {

7> AuthenticatingFilter: 實現判斷用戶是否有權限訪問某資源。

/** * An AuthenticationFilter that is capable of automatically performing an authentication attempt * based on the incoming request.*/public abstract class AuthenticatingFilter extends AuthenticationFilter {

8> FormAuthenticationFilter:shiro提供的用于實現用戶登錄功能,如果我們打算自己實現登錄,那么我們應用 PassThruAuthenticationFilter 來替代

/** * Requires the requesting user to be authenticated for the request to continue, and if they are not, forces the user * to login via by redirecting them to the setLoginUrl(String) you configure. * If you would prefer to handle the authentication validation and login in your own code, consider using the * PassThruAuthenticationFilter instead, which allows requests to the loginUrl to pass through to your application's code directly.*/public class FormAuthenticationFilter extends AuthenticatingFilter {

9> PassThruAuthenticationFilter : 用于我們自己在controller中實現登錄邏輯時替代FormAuthenticationFilter

/** * An authentication filter that redirects the user to the login page when they are trying to access * a protected resource. However, if the user is trying to access the login page, the filter lets * the request pass through to the application code. * The difference between this filter and the FormAuthenticationFilter is that * on a login submission (by default an HTTP POST to the login URL), the FormAuthenticationFilter filter * attempts to automatically authenticate the user by passing the username and password request parameter values to * Subject.login(AuthenticationToken) directly. * Conversely, this controller always passes all requests to the loginUrl through, both GETs and POSTs.   * This is useful in cases where the developer wants to write their own login behavior, which should include a * call to Subject.login(AuthenticationToken) at some point.  For example, if the developer has their own custom MVC  * login controller or validator, this PassThruAuthenticationFilter may be appropriate.*/public class PassThruAuthenticationFilter extends AuthenticationFilter {    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {        if (isLoginRequest(request, response)) {            return true;        } else {            saveRequestAndRedirectToLogin(request, response);            return false;        }    }}

10> Shiro 自帶的filter:

Shiro自身提供了很多的默認filter 來供我們使用,主要分為兩種:一是 登錄認證相關的filter;一是權限訪問控制相關的filter;

登錄認證相關的filter有:

1)filter名稱: anon, 實現類org.apache.shiro.web.filter.authc.AnonymousFilter,主要用于靜態資源的訪問,表示無需登錄就可以訪問;

2)filter名稱: authc, 實現類org.apache.shiro.web.filter.authc.FormAuthenticationFilter,主要用于表單登錄,沒有登錄則跳轉登錄url;

3)filter名稱: user, 實現類org.apache.shiro.web.filter.authc.UserFilter,主要用于要求用戶已經登錄或者通過“記住我”功能登錄了也行。

4)filter名稱: logout, 實現類org.apache.shiro.web.filter.authc.LogoutFilter,主要用于用戶登出

5)filter名稱:authcBasic,authc的簡化形式,略。

權限訪問控制相關的filter有:

1)filter名稱: roles, 實現類org.apache.shiro.web.filter.authc.RolesAuthorizationFilter,主要用于驗證用戶必須擁有某角色,才能繼續訪問;

2)filter名稱: perms, 實現類org.apache.shiro.web.filter.authc.PermissionsAuthorizationFilter,主要用于驗證用戶必須擁有某權限,才能繼續訪問;

3)filter名稱: ssl, 實現類org.apache.shiro.web.filter.authc.SslFilter,主要用于要求訪問協議是https才能訪問,不然跳轉到https的443短褲;

4)filter名稱: port rest noSessionCreation,略。

我們上面的shiroFilter的配置中,已經使用過了上面這些自帶的filter:

                /reg/** = anon    <!-- 注冊相關  -->                /login = authc                /logout = logout                /authenticated = authc                /loginController = anon                /js/** = anon                  /css/** = anon                   /img/** = anon                  /html/** = anon                /font-awesome/** = anon                  /** = user

我們看到 /reg/** 注冊相關的,/js/**靜態資源都是使用的 anon匿名過濾器,不要求用戶已經登錄就可以訪問。

/** = user 放在最后是要求除了上面那些 url 之外的訪問路徑,都需要登錄認證過或者通過記住我登錄認證過。因為路徑比較是從上面開始列出來的先開始比較的,匹配了就走該過濾器,不會繼續下面的過濾器了。

4. shiro的權限標簽

Shiro提供了相應的權限標簽,用來實現根據用戶的角色和權限來顯示它相應的菜單和按鈕。首先需要導入shiro標簽庫:

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

標簽庫的定義位于:shiro-web.jar 包中的META-INF/shiro.tld文件中:

<?xml version="1.0" encoding="ISO-8859-1" ?><!--  ~ Licensed to the Apache Software Foundation (ASF) under one  ~ or more contributor license agreements.  See the NOTICE file  ~ distributed with this work for additional information  ~ regarding copyright ownership.  The ASF licenses this file  ~ to you under the Apache License, Version 2.0 (the  ~ "License"); you may not use this file except in compliance  ~ with the License.  You may obtain a copy of the License at  ~  ~     http://www.apache.org/licenses/LICENSE-2.0  ~  ~ Unless required by applicable law or agreed to in writing,  ~ software distributed under the License is distributed on an  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY  ~ KIND, either express or implied.  See the License for the  ~ specific language governing permissions and limitations  ~ under the License.  --><!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD jsp Tag Library 1.2//EN"  "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd"><taglib>  <tlib-version>1.1.2</tlib-version>  <jsp-version>1.2</jsp-version>  <short-name>Apache Shiro</short-name>  <uri>http://shiro.apache.org/tags</uri>  <description>Apache Shiro JSP Tag Library.</description>  <tag>    <name>haspermission</name>    <tag-class>org.apache.shiro.web.tags.HasPermissionTag</tag-class>    <body-content>JSP</body-content>    <description>Displays body content only if the current Subject (user)      'has' (implies) the specified permission (i.e the user has the specified ability).    </description>    <attribute>      <name>name</name>      <required>true</required>      <rtexprvalue>true</rtexprvalue>    </attribute>  </tag>  <tag>    <name>lacksPermission</name>    <tag-class>org.apache.shiro.web.tags.LacksPermissionTag</tag-class>    <body-content>JSP</body-content>    <description>Displays body content only if the current Subject (user) does      NOT have (not imply) the specified permission (i.e. the user lacks the specified ability)    </description>    <attribute>      <name>name</name>      <required>true</required>      <rtexprvalue>true</rtexprvalue>    </attribute>  </tag>  <tag>    <name>hasRole</name>    <tag-class>org.apache.shiro.web.tags.HasRoleTag</tag-class>    <body-content>JSP</body-content>    <description>Displays body content only if the current user has the specified role.</description>    <attribute>      <name>name</name>      <required>true</required>      <rtexprvalue>true</rtexprvalue>    </attribute>  </tag>  <tag>    <name>hasAnyRoles</name>    <tag-class>org.apache.shiro.web.tags.HasAnyRolesTag</tag-class>    <body-content>JSP</body-content>    <description>Displays body content only if the current user has one of the specified roles from a      comma-separated list of role names.    </description>    <attribute>      <name>name</name>      <required>true</required>      <rtexprvalue>true</rtexprvalue>    </attribute>  </tag>  <tag>    <name>lacksRole</name>    <tag-class>org.apache.shiro.web.tags.LacksRoleTag</tag-class>    <body-content>JSP</body-content>    <description>Displays body content only if the current user does NOT have the specified role      (i.e. they explicitly lack the specified role)    </description>    <attribute>      <name>name</name>      <required>true</required>      <rtexprvalue>true</rtexprvalue>    </attribute>  </tag>  <tag>    <name>authenticated</name>    <tag-class>org.apache.shiro.web.tags.AuthenticatedTag</tag-class>    <body-content>JSP</body-content>    <description>Displays body content only if the current user has successfully authenticated      _during their current session_. It is more restrictive than the 'user' tag.      It is logically opposite to the 'notAuthenticated' tag.    </description>  </tag>  <tag>    <name>notAuthenticated</name>    <tag-class>org.apache.shiro.web.tags.NotAuthenticatedTag</tag-class>    <body-content>JSP</body-content>    <description>Displays body content only if the current user has NOT succesfully authenticated      _during their current session_. It is logically opposite to the 'authenticated' tag.    </description>  </tag>  <tag>    <name>user</name>    <tag-class>org.apache.shiro.web.tags.UserTag</tag-class>    <body-content>JSP</body-content>    <description>Displays body content only if the current Subject has a known identity, either      from a previous login or from 'RememberMe' services. Note that this is semantically different      from the 'authenticated' tag, which is more restrictive. It is logically      opposite to the 'guest' tag.    </description>  </tag>  <tag>    <name>guest</name>    <tag-class>org.apache.shiro.web.tags.GuestTag</tag-class>    <body-content>JSP</body-content>    <description>Displays body content only if the current Subject IS NOT known to the system, either      because they have not logged in or they have no corresponding 'RememberMe' identity. It is logically      opposite to the 'user' tag.    </description>  </tag>  <tag>    <name>principal</name>    <tag-class>org.apache.shiro.web.tags.PrincipalTag</tag-class>    <body-content>JSP</body-content>    <description>Displays the user's principal or a property of the user's principal.</description>    <attribute>      <name>type</name>      <required>false</required>      <rtexprvalue>true</rtexprvalue>    </attribute>    <attribute>      <name>property</name>      <required>false</required>      <rtexprvalue>true</rtexprvalue>    </attribute>    <attribute>      <name>defaultValue</name>      <required>false</required>      <rtexprvalue>true</rtexprvalue>    </attribute>  </tag></taglib>
shiro.tld

其中最重要的標簽是關于角色和權限的:

<shiro:hasAnyRoles name="student,teacher"></shiro:hasAnyRoles>

<shiro:hasPermission name="user:delete"></shiro:hashPermission>

其它還有關于登錄與否的標簽:

<shiro:guest></shiro:guest> 未登錄可以顯示的信息;

<shiro:user></shiro:user> 用戶已經登錄或者通過記住我登錄后顯示的信息;

<shiro:authenticated></shiro:authenticated> 必須是實際登錄,不是通過記住我登錄的

其它標簽參考 shiro.tld文件。

shiro標簽使用示例:

<!--sidebar-menu--><div id="sidebar"><a href="Javascript:;" class="visible-phone"><i class="icon icon-home"></i> Dashboard</a>  <ul>  <shiro:hasAnyRoles name="student,teacher">      <li id="li_queryScore"><a href="${ctx}/user/queryScore"><i class="icon icon-home"></i><span>查詢成績</span></a></li>  </shiro:hasAnyRoles>  <shiro:hasAnyRoles name="teacher,admin">      <li id="li_showStudentInfo"><a href="${ctx}/student/showStudentInfo"><i class="icon icon-home"></i><span>查詢學生信息</span></a></li>  </shiro:hasAnyRoles>  <shiro:hasAnyRoles name="admin">    <li id="li_showTeacherInfo"><a href="${ctx}/teacher/showTeacherInfo"><i class="icon icon-home"></i><span>查詢教師信息</span></a></li>  </shiro:hasAnyRoles>   <shiro:hasAnyRoles name="admin">    <li id="li_getStatistic"><a href="${ctx}/statistics/getStatistic"><i class="icon icon-th"></i><span>統計</span></a></li>  </shiro:hasAnyRoles>      <shiro:hasAnyRoles name="student,teacher,admin">    <li id="li_password"><a href="${ctx}/user/password"><i class="icon icon-inbox"></i><span>密碼修改</span></a></li>  </shiro:hasAnyRoles>    <shiro:hasRole name="admin">      <li id="li_showPrivilege"><a href="${ctx}/priv/showPrivilege"><i class="icon icon-fullscreen"></i><span>權限設置</span></a></li>  </shiro:hasRole>  <shiro:hasAnyRoles name="teacher">      <li id="li_scoreRatio"><a href="${ctx}/set/scoreRatio"><i class="icon icon-tint"></i><span>成績比例設置</span></a></li>  </shiro:hasAnyRoles>   <shiro:hasAnyRoles name="admin">      <li id="li_getSetting"><a href="${ctx}/set/getSetting"><i class="icon icon-tint"></i><span>成績錄入時間設置</span></a></li>  </shiro:hasAnyRoles>   <shiro:hasAnyRoles name="student,teacher">      <li id="li_queryReExam"><a href="${ctx}/user/queryReExam"><i class="icon icon-pencil"></i><span>補考名單</span></a></li>    <li id="li_queryReLearn"><a href="${ctx}/user/queryReLearn"><i class="icon icon-pencil"></i><span>重修名單</span></a></li>  </shiro:hasAnyRoles>    </ul></div><!--sidebar-menu-->
View Code

效果是根據用戶擁有的角色,來顯示左側有哪些菜單項。

5. shiro 權限注解的使用

shiro對權限的控制,除了前面給出的在 shiroFilter這個bean中配置的過濾器:

<property name="filterChainDefinitions">            <value>                /reg/** = anon    <!-- 注冊相關  -->                /login = authc                /logout = logout                /loginController = anon                /js/** = anon                  /css/** = anon                   /img/** = anon                  /html/** = anon                /font-awesome/** = anon                  /** = user            </value>        </property>

之外,最重要的就是使用注解的方式來進行訪問控制的實現了。shiro權限注解可以達到方法級別的細膩控制,可以控制具有某些權限或者某些角色的用戶才能訪問某個方法(某個url)。先要開啟shiro權限注解功能,開啟方法參見文檔:http://shiro.apache.org/spring.html

Here is how to enable these annotations. Just add these two bean definitions to applicationContext.xml:

<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/><!-- Enable Shiro Annotations for Spring-configured beans.  Only run after --><!-- the lifecycleBeanProcessor has run: --><bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/><bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">    <property name="securityManager" ref="securityManager"/></bean>

開啟shiro權限注解的方法二

    <aop:config />    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">        <property name="securityManager" ref="securityManager"/>    </bean>

<aop:config /> 表示開啟spring注解,而 DefaultAdvisorAutoProxyCreator 表示會自動創建代理。但是二者最好不要同時使用。

AuthorizationAttributeSourceAdvisor 通過其依賴的 securityManager 來獲取用戶的角色和權限信息,進而可以進行權限判斷。

支持的shiro注解有:

@SuppressWarnings({"unchecked"})public class AuthorizationAttributeSourceAdvisor extends StaticMethodMatcherPointcutAdvisor {    private static final Logger log = LoggerFactory.getLogger(AuthorizationAttributeSourceAdvisor.class);    private static final Class<? extends Annotation>[] AUTHZ_ANNOTATION_CLASSES =            new Class[] {                    RequiresPermissions.class, RequiresRoles.class,                    RequiresUser.class, RequiresGuest.class, RequiresAuthentication.class            };    protected SecurityManager securityManager = null; public AuthorizationAttributeSourceAdvisor() { setAdvice(new AopAllianceAnnotationsAuthorizingMeth
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 大西瓜永久免费av在线 | 久久国产成人午夜av浪潮 | 国产精品自拍av | 国产一级二级毛片 | 国产pron | 精品久久久久久久久久久久久久久久久久久 | 国产精品视频一区二区三区综合 | 色综合欧美 | 麻豆蜜桃在线观看 | 黄视频免费在线观看 | 天堂福利电影 | 日韩黄色成人 | 在线播放免费视频 | 欧美hdfree性xxxx | 手机国产乱子伦精品视频 | 男男羞羞视频网站国产 | 国产精品久久久久久久久粉嫩 | 欧洲精品久久久久69精品 | 久久一区三区 | 久久噜噜噜 | 88xx成人永久免费观看 | 久久久久久久久久91 | 久久蜜桃香蕉精品一区二区三区 | 国产成人精品午夜视频' | 国产精品区一区二区三区 | 91久久久久久久久久久久久久 | 激情小说激情电影 | 免费看欧美黑人毛片 | 在线天堂中文在线资源网 | 久久免费观看一级毛片 | 日本高清com | 在线成人一区二区 | 国产精品一区二区三区99 | 护士xxxx | 黄色一级电影网 | 精品日韩欧美 | 一级成人在线 | 色视频在线| 亚洲天堂在线电影 | 双性精h调教灌尿打屁股的文案 | 一级免费视频 |