Shiro简介和Quickstart

Shiro安全框架

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、加密、会话管理、与 Web 集成、缓存等。相当简单,对比 Spring Security,可能没有 Spring Security 做的功能强大。Shiro 可以非常容易的开发出足够好的应用,其不仅可以用在 JavaSE 环境,也可以用在 JavaEE 环境。

功能点:

Authentication:身份认证 / 登录,验证用户是不是拥有相应的身份;
Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;
Session Management:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通 JavaSE 环境的,也可以是如 Web 环境的;
Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;
Web Support:Web 支持,可以非常容易的集成到 Web 环境;
Caching:缓存,比如用户登录后,其用户信息、拥有的角色 / 权限不必每次去查,这样可以提高效率;
Concurrency:shiro 支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;
Testing:提供测试支持;
Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;
Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。

Shiro三大核心组件

       Subject:即“当前操作用户”。但是,在Shiro中,Subject这一概念并不仅仅指人,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。它仅仅意味着“当前跟软件交互的东西”。Subject代表了当前用户的安全操作,所有 Subject 都绑定到 SecurityManager,SecurityManager则管理所有用户的安全操作。
  SecurityManager:安全管理器,它是Shiro框架的核心,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。
  Realm: Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。从这个意义上讲,Realm实质上是一个安全相关的DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给Shiro。当配置Shiro时,你必须至少指定一个Realm,用于认证和(或)授权。配置多个Realm是可以的,但是至少需要一个。

身份认证

在 shiro 中,用户需要提供 principals (身份)和 credentials(证明)给 shiro,从而应用能验证用户身份:

身份验证 :一般需要提供如身份 ID 等一些标识信息来表明登录者的身 份,如提供 email, 用户名/密码 来证明。
        在 shiro 中,用户需要提供 principals (身份)和 credentials(证 明) 给 shiro,从而应用能验证用户身份:
principals :身份,即 主体的标识属性 ,可以是任何属性, 如用户名、 邮箱等,唯一即可 。一个主体可以有多个 principals,但 只有一个 Primary principals ,一般是用户名/邮箱/手机号。
credentials 证明/凭证 ,即只有主体知道的安全值,如密码/数字证 书等。
 
最常见的 principals 和 credentials 组合就是 用户名/密码 了,外两个相关的概念是之前提到的  Subject 及  Realm,分别是主体及验证主体的数据源
 

授权

授权 ,也叫 访问控制,即在应用中控制谁访问哪些资源 (如访问页面/编辑数据/页面操作 等)。在授权中需了解的几个关键对象:主体(Subject)、资源(Resource)、权限 (Permission)、角色(Role)。
 
      1、  主体(Subject): 访问应用的用户,在 Shiro 中使用 Subject 代表该用户。用户只有授权 后才允许访问相应的资源。
      2、 资源(Resource): 在应用中用户可以访问的 URL ,比如访问 JSP 页面、查看/编辑某些数据、访问某个业务方法、打印文本等等都是资源。用户只要授权后才能访问。
      3、 权限(Permission): 安全策略中的原子授权单位,通过权限我们可以表示在应用中用户有没有操作某个资源的权力。即 权限表示在应用中用户能不能访问某个资源 ,如:访问用户列表页面查看/新增/修改/删除用户数据(即很多时候都是CRUD(增查改删)式权限控制)等。权限代表了用户有没有操作某个资源的权利,即反映在某个资源上的操作允不允许。
      4、 角色(Role) 权限的集合 ,一般情况下会赋予用户角色而不是权限,即这样用户可以拥有 一组权限,赋予权限时比较方便。典型的如:项目经理、技术总监、CTO、开发工程师等 都是角色,不同的角色拥有一组不同的权限。
 

Quickstart 

shrio.ini

[users]#用户=密码,角色
root = secret, admin  
guest = guest, guest
presidentskroob = 12345, president
darkhelmet = ludicrousspeed, darklord, schwartz
lonestarr = vespa, goodguy, schwartz


[roles]#角色=权限(角色具有的权限)
admin = *
schwartz = lightsaber:*
goodguy = user:delete:zhangsan

 

public class Quickstart {

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

    public static void main(String[] args) {

		//创建shrio核心 securityManager
        Factory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
        SecurityManager securityManager = factory.getInstance();
        SecurityUtils.setSecurityManager(securityManager);

        //创建subject
        Subject currentUser = SecurityUtils.getSubject();

        //获取session
        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 + "]");
        }

        //测试当前用户是否已经认证,即是否登录
        if (!currentUser.isAuthenticated()) {
        	// 将用户名和密码封装为 UsernamePasswordToken
            UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
            // rememberme:免登录也可访问,authc的资源必须登录才行
            token.setRememberMe(true);
            try {
            	//执行登录  即后面的realm的认证方法  将token给realm  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException{}方法  
                currentUser.login(token);
            } 
            // 未知的账户 
            catch (UnknownAccountException uae) {
                log.info("----> There is no user with username of " + token.getPrincipal());
                return; 
            } 
            // 密码不正确 
            catch (IncorrectCredentialsException ice) {
                log.info("----> Password for account " + token.getPrincipal() + " was incorrect!");
                return; 
            } 
            //账户呗锁定
            catch (LockedAccountException lae) {
                log.info("The account for username " + token.getPrincipal() + " is locked.  " +
                        "Please contact your administrator to unlock it.");
            }
            // 
            catch (AuthenticationException ae) {
                //unexpected condition?  error?
            }
        }

        log.info("----> User [" + currentUser.getPrincipal() + "] logged in successfully.");
     
        // 是否有schwartz的角色
        if (currentUser.hasRole("schwartz")) {
            log.info("----> May the Schwartz be with you!");
        } else {
            log.info("----> Hello, mere mortal.");
            return; 
        }

       
        //是否有lightsaber:weild的权限(测试用户是否有什么行为)
        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.");
        }

       
        //
        if (currentUser.isPermitted("user:delete:zhangsan")) {
            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!");
        }

      
        //登出
        System.out.println("---->" + currentUser.isAuthenticated());
        currentUser.logout();
        System.out.println("---->" + currentUser.isAuthenticated());
        System.exit(0);
    }
}

 

你可能感兴趣的:(权限管理)