Shiro的原理及Web搭建

shiro(java安全框架)


 

    如下都是綜合以前的人加上本身的一些小總結html

    Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、受權、密碼學和會話管理。使用Shiro的易於理解的API,您能夠快速、輕鬆地得到任何應用程序,從最小的移動應用程序到最大的網絡和企業應用程序。java

Shiro 主要分爲來個部分就是認證和受權,在我的感受來看就是查詢數據庫作相應的判斷而已,Shiro只是一個框架而已,其中的內容須要本身的去構建,先後是本身的,中間是Shiro幫咱們去搭建和配置好的web

    我的認爲須要看一下其中的一些源碼,更有幫助的深刻的去了解Shiro的原理。spring

Shiro的主要框架圖:

     image

 

方法類的走向:

 

對一些其中的方法的簡單說明:

Subject

Subject即主體,外部應用與subject進行交互,subject記錄了當前操做用戶,將用戶的概念理解爲當前操做的主體,多是一個經過瀏覽器請求的用戶,也多是一個運行的程序。 Subject在shiro中是一個接口,接口中定義了不少認證授相關的方法,外部程序經過subject進行認證授,而subject是經過SecurityManager安全管理器進行認證受權數據庫

 SecurityManager 

SecurityManager即安全管理器,對所有的subject進行安全管理,它是shiro的核心,負責對全部的subject進行安全管理。經過SecurityManager能夠完成subject的認證、受權等,實質上SecurityManager是經過Authenticator進行認證,經過Authorizer進行受權,經過SessionManager進行會話管理等。apache

SecurityManager是一個接口,繼承了Authenticator, Authorizer, SessionManager這三個接口。api

 Authenticator

Authenticator即認證器,對用戶身份進行認證,Authenticator是一個接口,shiro提供ModularRealmAuthenticator實現類,經過ModularRealmAuthenticator基本上能夠知足大多數需求,也能夠自定義認證器。瀏覽器

Authorizer

Authorizer即受權器,用戶經過認證器認證經過,在訪問功能時須要經過受權器判斷用戶是否有此功能的操做權限。spring-mvc

 realm

Realm即領域,至關於datasource數據源,securityManager進行安全認證須要經過Realm獲取用戶權限數據,好比:若是用戶身份數據在數據庫那麼realm就須要從數據庫獲取用戶身份信息。緩存

注意:不要把realm理解成只是從數據源取數據,在realm中還有認證受權校驗的相關的代碼。

 sessionManager

sessionManager即會話管理,shiro框架定義了一套會話管理,它不依賴web容器的session,因此shiro可使用在非web應用上,也能夠將分佈式應用的會話集中在一點管理,此特性可以使它實現單點登陸。

 SessionDAO

SessionDAO即會話dao,是對session會話操做的一套接口,好比要將session存儲到數據庫,能夠經過jdbc將會話存儲到數據庫。

CacheManager

CacheManager即緩存管理,將用戶權限數據存儲在緩存,這樣能夠提升性能。

Cryptography

Cryptography即密碼管理,shiro提供了一套加密/解密的組件,方便開發。好比提供經常使用的散列、加/解密等功能。

 

shiro認證與受權的在Web中實現


第一步:添加jar包


 

 <!-- shiro -->
    <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>

第二步:配置web.xml


 

  <!-- shiro 過濾器 start -->
  <filter>
    <filter-name>shiroFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <!-- 設置true由servlet容器控制filter的生命週期 -->
    <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>
  <!-- shiro 過濾器 end -->

第三步:自定義Realm 繼承AuthorizingRealm 重寫  AuthorizationInfo(受權) 和  AuthenticationInfo(認證)


 

如下只是簡單的測試

如下都是根據我的的設置和需求改變的。如今數據是死的,運用的時候須要從數據庫中獲得

/**
 * @author zhouguanglin
 * @date 2018/2/26 14:05
 */
public class CustomRealm extends AuthorizingRealm {
    /**
     * 受權
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String userName = (String) principalCollection.getPrimaryPrincipal();
        List<String> permissionList=new ArrayList<String>();
        permissionList.add("user:add");
        permissionList.add("user:delete");
        if (userName.equals("zhou")) {
            permissionList.add("user:query");
        }
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        info.addStringPermissions(permissionList);
        info.addRole("admin");
        return info;
    }
    /**
     * 認證
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String userName = (String) authenticationToken.getPrincipal();
        if ("".equals(userName)) {
            return  null;
        }
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName,"123456",this.getName());
        return info;
    }
}

第四步:配置spring-shiro.xml


 

這裏面都是按照本身的需求去配置的

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--開啓shiro的註解-->
    <bean id="advisorAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator">
        <property name="proxyTargetClass" value="true"></property>
    </bean>
    <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"/>
    <!--注入自定義的Realm-->
    <bean id="customRealm" class="com.test.realm.CustomRealm"></bean>
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="customRealm"></property>
    </bean>

    <!--配置ShiroFilter-->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"></property>
        <!--登入頁面-->
        <property name="loginUrl" value="/login.jsp"></property>
        <!--登入成功頁面-->
        <property name="successUrl" value="/index.jsp"/>
        <property name="filters">
            <map>
                <!--退出過濾器-->
                <entry key="logout" value-ref="logoutFilter" />
            </map>
        </property>
        <!--URL的攔截-->
        <property name="filterChainDefinitions" >
            <value>
                /share = authc
                /logout = logout
            </value>
        </property>

    </bean>
    <!--自定義退出LogoutFilter-->
    <bean id="logoutFilter" class="com.test.filter.SystemLogoutFilter">
        <property name="redirectUrl" value="/login"/>
    </bean>
</beans>

一些屬性的意義:

securityManager: 這個屬性是必須的。

loginUrl: 沒有登陸的用戶請求須要登陸的頁面時自動跳轉到登陸頁面,不是必須的屬性,不輸入地址的話會自動尋找項目web項目的根目錄下的」/login.jsp」頁面。

successUrl: 登陸成功默認跳轉頁面,不配置則跳轉至」/」。若是登錄前點擊的一個須要登陸的頁面,則在登陸自動跳轉到那個須要登陸的頁面。不跳轉到此。

unauthorizedUrl: 沒有權限默認跳轉的頁面。

Shiro中默認的過濾器:

 

過濾器名稱 過濾器類 描述
anon org.apache.shiro.web.filter.authc.AnonymousFilter 匿名過濾器
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter 若是繼續操做,須要作對應的表單驗證不然不能經過
authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter 基本http驗證過濾,若是不經過,跳轉屋登陸頁面
logout org.apache.shiro.web.filter.authc.LogoutFilter 登陸退出過濾器
noSessionCreation org.apache.shiro.web.filter.session.NoSessionCreationFilter 沒有session建立過濾器
perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter 權限過濾器
port org.apache.shiro.web.filter.authz.PortFilter 端口過濾器,能夠設置是不是指定端口若是不是跳轉到登陸頁面
rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter http方法過濾器,能夠指定如post不能進行訪問等
roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter 角色過濾器,判斷當前用戶是否指定角色
ssl org.apache.shiro.web.filter.authz.SslFilter 請求須要經過ssl,若是不是跳轉回登陸頁
user org.apache.shiro.web.filter.authc.UserFilter 若是訪問一個已知用戶,好比記住我功能,走這個過濾器

 

在spring中直接引入<import resource="spring-shiro.xml"></import>

第五步:在spring-mvc.xml中配置權限的控制 異常的跳轉

 <!-- 未認證或未受權時跳轉必須在springmvc裏面配,spring-shiro裏的shirofilter配不生效 -->
    <bean   class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <!--表示捕獲的異常 -->
                <prop key="org.apache.shiro.authz.UnauthorizedException">
                    <!--捕獲該異常時跳轉的路徑 -->
                    /403
                </prop>
                <!--表示捕獲的異常 -->
                <prop key="org.apache.shiro.authz.UnauthenticatedException">
                    <!--捕獲該異常時跳轉的路徑 -->
                    /403
                </prop>
            </props>
        </property>
    </bean>

403是錯誤頁面

第六步:在controller中測試使用的驗證登入


    @RequestMapping(value = "/login", method = RequestMethod.POST)
    public String login(String userName, String passwd, Model model) {
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(userName, passwd);
        try {
            subject.login(token);
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            model.addAttribute("userName", "用戶名錯誤!");
            return "login";
        } catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            model.addAttribute("passwd", "密碼錯誤");
            return "login";
        }
        return "index";
    }

以後的都是HTML頁面的跳轉

有關HTML中的一些shiro設置:

在使用Shiro標籤庫前,首先須要在JSP引入shiro標籤: 

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

一、介紹Shiro的標籤guest標籤 :驗證當前用戶是否爲「訪客」,即未認證(包含未記住)的用戶。

1
2
3
4
5
<shiro:guest> 
 
Hi there!  Please <a href= "login.jsp" >Login</a> or <a href= "signup.jsp" >Signup</a> today! 
 
</shiro:guest>

  

二、user標籤 :認證經過或已記住的用戶。

1
2
3
4
5
<shiro:user> 
 
     Welcome back John!  Not John? Click <a href= "login.jsp" >here<a> to login. 
 
</shiro:user>

  

三、authenticated標籤 :已認證經過的用戶。不包含已記住的用戶,這是與user標籤的區別所在。

1
2
3
4
5
<shiro:authenticated> 
 
     <a href= "updateAccount.jsp" >Update your contact information</a>. 
 
</shiro:authenticated>

  

四、notAuthenticated標籤 :未認證經過用戶,與authenticated標籤相對應。與guest標籤的區別是,該標籤包含已記住用戶。 

1
2
3
4
5
<shiro:notAuthenticated> 
 
     Please <a href= "login.jsp" >login</a> in order to update your credit card information. 
 
</shiro:notAuthenticated>

  

五、principal 標籤 :輸出當前用戶信息,一般爲登陸賬號信息。

1
Hello, <shiro:principal/>, how are you today?

  

六、hasRole標籤 :驗證當前用戶是否屬於該角色。

1
2
3
4
5
<shiro:hasRole name= "administrator"
 
     <a href= "admin.jsp" >Administer the system</a> 
 
</shiro:hasRole>

  

七、lacksRole標籤 :與hasRole標籤邏輯相反,當用戶不屬於該角色時驗證經過。

1
2
3
4
5
<shiro:lacksRole name= "administrator"
 
     Sorry, you are not allowed to administer the system. 
 
</shiro:lacksRole>

  

八、hasAnyRole標籤 :驗證當前用戶是否屬於如下任意一個角色。 

1
2
3
4
5
<shiro:hasAnyRoles name= "developer, project manager, administrator"
 
     You are either a developer, project manager, or administrator. 
 
</shiro:lacksRole>

  

九、hasPermission標籤 :驗證當前用戶是否擁有指定權限。

1
2
3
4
5
<shiro:hasPermission name= "user:create"
 
     <a href= "createUser.jsp" >Create a  new  User</a> 
 
</shiro:hasPermission>

十、lacksPermission標籤 :與hasPermission標籤邏輯相反,當前用戶沒有制定權限時,驗證經過。

1
2
3
4
5
<shiro:hasPermission name= "user:create"
 
     <a href= "createUser.jsp" >Create a  new  User</a> 
 
</shiro:hasPermission>

 

參考文章 :

http://www.cnblogs.com/yangang2013/p/5716928.html

https://www.cnblogs.com/jifeng/p/4500410.html

 

轉載請註明出處:http://www.cnblogs.com/zhouguanglin/p/8477807.html 

相關文章
相關標籤/搜索