1. 程式人生 > >shiro簡單入門介紹

shiro簡單入門介紹

shiro是apache的一個java安全框架

可以完成認證,授權,加密,會話管理,基於web繼承,快取等

功能簡介:

 

 從外部來看:

 

shiro架構

 Subject:主體,代表了當前“使用者”,這個使用者不一定是一個具體的人,與當前應用互動的任何東西都是Subject,如網路爬蟲,機器人等;即一個抽象概念;所有Subject都繫結到SecurityManager,與Subject的所有互動都會委託給SecurityManager;可以把Subject認為是一個門面;SecurityManager才是實際的執行者;

SecurityManager
:安全管理器;即所有與安全有關的操作都會與SecurityManager互動;且它管理著所有Subject;可以看出它是Shiro的核心,它負責與後邊介紹的其他元件進行互動,如果學習過SpringMVC,你可以把它看成DispatcherServlet前端控制器; Realm:域,Shiro從從Realm獲取安全資料(如使用者、角色、許可權),就是說SecurityManager要驗證使用者身份,那麼它需要從Realm獲取相應的使用者進行比較以確定使用者身份是否合法;也需要從Realm得到使用者相應的角色/許可權進行驗證使用者是否能進行操作;可以把Realm看成DataSource,即安全資料來源。

 

 從內部看:

 

Subject:主體,可以看到主體可以是任何可以與應用互動的“使用者”;

SecurityManager相當於SpringMVC中的DispatcherServlet或者Struts2中的FilterDispatcher;是Shiro的心臟;所有具體的互動都通過SecurityManager進行控制;它管理著所有Subject、且負責進行認證和授權、及會話、快取的管理。 Authenticator:認證器,負責主體認證的,這是一個擴充套件點,如果使用者覺得Shiro預設的不好,可以自定義實現;其需要認證策略(Authentication Strategy),即什麼情況下算使用者認證通過了; Authrizer
:授權器,或者訪問控制器,用來決定主體是否有許可權進行相應的操作;即控制著使用者能訪問應用中的哪些功能; Realm:可以有1個或多個Realm,可以認為是安全實體資料來源,即用於獲取安全實體的;可以是JDBC實現,也可以是LDAP實現,或者記憶體實現等等;由使用者提供;注意:Shiro不知道你的使用者/許可權儲存在哪及以何種格式儲存;所以我們一般在應用中都需要實現自己的Realm; SessionManager:如果寫過Servlet就應該知道Session的概念,Session呢需要有人去管理它的生命週期,這個元件就是SessionManager;而Shiro並不僅僅可以用在Web環境,也可以用在如普通的JavaSE環境、EJB等環境;所有呢,Shiro就抽象了一個自己的Session來管理主體與應用之間互動的資料;這樣的話,比如我們在Web環境用,剛開始是一臺Web伺服器;接著又上了臺EJB伺服器;這時想把兩臺伺服器的會話資料放到一個地方,這個時候就可以實現自己的分散式會話(如把資料放到Memcached伺服器); SessionDAO:DAO大家都用過,資料訪問物件,用於會話的CRUD,比如我們想把Session儲存到資料庫,那麼可以實現自己的SessionDAO,通過如JDBC寫到資料庫;比如想把Session放到Memcached中,可以實現自己的Memcached SessionDAO;另外SessionDAO中可以使用Cache進行快取,以提高效能; CacheManager:快取控制器,來管理如使用者、角色、許可權等的快取的;因為這些資料基本上很少去改變,放到快取中後可以提高訪問的效能 Cryptography:密碼模組,Shiro提高了一些常見的加密元件用於如密碼加密/解密的。

 

下載地址:

http://shiro.apache.org/download.html

 

 

 HellowWord:

package cn.com.MrChengs.helloword;
/*
* 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.
*/

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
* Simple Quickstart application showing how to use Shiro's API.
*
* @since 0.9 RC2
*/
public class Quickstart {

    private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);


    public static void main(String[] args) {

        // The easiest way to create a Shiro SecurityManager with configured
        // realms, users, roles and permissions is to use the simple INI config.
        // We'll do that by using a factory that can ingest a .ini file and
        // return a SecurityManager instance:

        // Use the shiro.ini file at the root of the classpath
        // (file: and url: prefixes load from files and urls respectively):
        Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        SecurityManager securityManager = factory.getInstance();

        // for this simple example quickstart, make the SecurityManager
        // accessible as a JVM singleton.  Most applications wouldn't do this
        // and instead rely on their container configuration or web.xml for
        // webapps.  That is outside the scope of this simple quickstart, so
        // we'll just do the bare minimum so you can continue to get a feel
        // for things.
        SecurityUtils.setSecurityManager(securityManager);

        // Now that a simple Shiro environment is set up, let's see what you can do:

        // get the currently executing user:
        //獲取當前的subject
        //呼叫SecurityUtils.getSubject();
        Subject currentUser = SecurityUtils.getSubject();

        // Do some stuff with a Session (no need for a web or EJB container!!!)
        //測試使用session
        //首先獲取session:currentUser.getSession();
        //
        Session session = currentUser.getSession();
        session.setAttribute("someKey", "aValue");
        String value = (String) session.getAttribute("someKey");
        if (value.equals("aValue")) {
            log.info("--->Retrieved the correct value! [" + value + "]");
        }

        // let's login the current user so we can check against roles and permissions:
        //測試當前使用者是否已經被認證,即是否已經登陸
        //呼叫subject的isAuthenticated()
        
        
        if (!currentUser.isAuthenticated()) {
            //把使用者名稱和密碼封裝為UsernamePasswordToken物件
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
            token.setRememberMe(true);
            try {
                //執行登陸
                currentUser.login(token);
            }
            //若沒有指定的訊息,則shiro會丟擲UnknownAccountException異常
            catch (UnknownAccountException uae) {
                log.info("There is no user with username of " + token.getPrincipal());
            }
            //若賬戶存在,但是密碼不匹配則丟擲IncorrectCredentialsException
            catch (IncorrectCredentialsException ice) {
                log.info("Password for account " + token.getPrincipal() + " was incorrect!");
            }
            //使用者被鎖定的異常
            catch (LockedAccountException lae) {
                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            }
            // ... catch more exceptions here (maybe custom ones specific to your application?
            //所有認證時的異常父類
            catch (AuthenticationException ae) {
                //unexpected condition?  error?
            }
        }

        //say who they are:
        //print their identifying principal (in this case, a username):
        log.info("User [" + currentUser.getPrincipal() + "] logged in successfully.");

        //test a role:
        //測試是否有某一個角色
        if (currentUser.hasRole("schwartz")) {
            log.info("May the Schwartz be with you!");
        } else {
            log.info("Hello, mere mortal.");
        }

        //test a typed permission (not instance-level)
        //測試是否具有某一個行為
        if (currentUser.isPermitted("lightsaber:weild")) {
            log.info("You may use a lightsaber ring.  Use it wisely.");
        } else {
            log.info("Sorry, lightsaber rings are for schwartz masters only.");
        }

        //a (very powerful) Instance Level permission:
        //測試使用者是否具備某一個行為
        if (currentUser.isPermitted("winnebago:drive:eagle5")) {
            log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'.  " +
                    "Here are the keys - have fun!");
        } else {
            log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");
        }

        //all done - log out!
        //執行登出
        currentUser.logout();
}

執行即可體驗shiro的簡單功能....