前言

看到这篇文章之前,可能很多小伙伴都没听过shiro,那么shiro是什么呢?shiro是Apache基金会下一个非常有名的开源项目(项目官网: http://shiro.apache.org/ ),官网是这样介绍的:

Apache Shiro™是一个功能强大且易于使用的Java安全框架,它执行身份验证、授权、加密和会话管理。使用Shiro易于理解的API,您可以快速轻松地保护任何应用程序—从最小的移动应用程序到最大的Web和企业应用程序。

接下来就让我们近距离地了解shiro吧。

一、创建maven项目

1.选择maven模板,填写项目信息

选择maven,这里我选择的模板是quickstart

填写项目信息

设置项目maven配置,如果没有特殊设置,直接下一步

设置项目保存路径

maven项目到此创建完成,下面开始shiro demo

二、编写shiro demo

1.导入依赖包

导入如下依赖

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.2.6</version>
</dependency>
2.编写java
package io.github.syske;/*
* 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 currentUser = SecurityUtils.getSubject(); // Do some stuff with a Session (no need for a web or EJB container!!!)
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:
if (!currentUser.isAuthenticated()) {
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
token.setRememberMe(true);
try {
currentUser.login(token);
} catch (UnknownAccountException uae) {
log.info("There is no user with username of " + token.getPrincipal());
} 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:wield")) {
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(); System.exit(0);
}
}

当然你也可以直接导入shiro官方的示例代码,以上代码就是来源于官方示例

3.导入配置文件

日志配置文件,文件名log4j.properties

log4j.rootLogger=INFO, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n # General Apache libraries
log4j.logger.org.apache=WARN # Spring
log4j.logger.org.springframework=WARN # Default Shiro logging
log4j.logger.org.apache.shiro=INFO # Disable verbose logging
log4j.logger.org.apache.shiro.util.ThreadContext=WARN
log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN

shiro配置文件,文件名shiro.ini

#
# 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.
#
# =============================================================================
# Quickstart INI Realm configuration
#
# For those that might not understand the references in this file, the
# definitions are all based on the classic Mel Brooks' film "Spaceballs". ;)
# ============================================================================= # -----------------------------------------------------------------------------
# Users and their assigned roles
#
# Each line conforms to the format defined in the
# org.apache.shiro.realm.text.TextConfigurationRealm#setUserDefinitions JavaDoc
# -----------------------------------------------------------------------------
[users]
# user 'root' with password 'secret' and the 'admin' role
root = secret, admin
# user 'guest' with the password 'guest' and the 'guest' role
guest = guest, guest
# user 'presidentskroob' with password '12345' ("That's the same combination on
# my luggage!!!" ;)), and role 'president'
presidentskroob = 12345, president
# user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'
darkhelmet = ludicrousspeed, darklord, schwartz
# user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz'
lonestarr = vespa, goodguy, schwartz # -----------------------------------------------------------------------------
# Roles with assigned permissions
#
# Each line conforms to the format defined in the
# org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc
# -----------------------------------------------------------------------------
[roles]
# 'admin' role has all permissions, indicated by the wildcard '*'
admin = *
# The 'schwartz' role can do anything (*) with any lightsaber:
schwartz = lightsaber:*
# The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with
# license plate 'eagle5' (instance specific id)
goodguy = winnebago:drive:eagle5

这里依然放上官方示例的配置文件

三、运行

直接运行java中的main方法即可,这里需要注意的是shiro项目的日志需要slf4j,所以要导入slf4j的依赖,依赖如下:

    <!-- configure logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.24</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.24</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<scope>runtime</scope>
</dependency> <dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.24</version>
</dependency>

然后,你就能看到控制台打印如下日志信息:

2019-10-19 12:00:04,751 INFO [org.apache.shiro.session.mgt.AbstractValidatingSessionManager] - Enabling session validation scheduler...
2019-10-19 12:00:05,508 INFO [io.github.syske.Quickstart] - Retrieved the correct value! [aValue]
2019-10-19 12:00:05,512 INFO [io.github.syske.Quickstart] - User [lonestarr] logged in successfully.
2019-10-19 12:00:05,512 INFO [io.github.syske.Quickstart] - May the Schwartz be with you!
2019-10-19 12:00:05,513 INFO [io.github.syske.Quickstart] - You may use a lightsaber ring. Use it wisely.
2019-10-19 12:00:05,514 INFO [io.github.syske.Quickstart] - You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'. Here are the keys - have fun!

至此,我们的第一个shiro demo已经正常运行了,下来让我们分析解释下上面的代码

四、代码解析

这里只探讨shiro的相关代码,log4j配置这里不讨论,如果想了解的小伙伴可以自己查阅相关资料,当然也可以给我留言。

1.shiro配置文件

我删除了官方英文注释,将核心的注释翻译成了中文,然后加入了比较详细的说明

[users]
# 用户root的密码为secret,角色为admin(也就是说配置的方法是:用户名=密码, 角色)
root = secret, admin
# 用户guest的密码为guest,角色为guest(同上)
guest = guest, guest
# 用户presidentskroob的密码为12345,用户角色president
presidentskroob = 12345, president
# 下面这个是给用户配置多角色,用户darkhelmet的密码为ludicrousspeed,角色为darklord和schwartz
darkhelmet = ludicrousspeed, darklord, schwartz
# 用户lonestarr的密码为vespa,角色为goodguy和schwartz
lonestarr = vespa, goodguy, schwartz [roles]
# 这里是给角色设置权限,下面配置的意思是,角色admin可以访问所有资源(*标识匹配所有,具体的匹配规则后面会
#讲到)
admin = *
# 拥有lightsaber权限的角色可以访问所有资源(*)
schwartz = lightsaber:*
# 角色goodguy可以通过携带eagle5(实例特定ID)的方式访问winnebago类型的资源
goodguy = winnebago:drive:eagle5
2.java代码
public static void main(String[] args) {
// 创建SecurityManager工厂
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
// 通过工厂创建SecurityManager实例
SecurityManager securityManager = factory.getInstance();
// 将securityManager传给SecurityUtils
SecurityUtils.setSecurityManager(securityManager);
// 从SecurityUtils中获取Subject实例
Subject currentUser = SecurityUtils.getSubject();
/* 从Subject实例中获取Session实例
这里需要说明的是shiro的Session非常强大,不仅可以在web中使用,而且可以在J2SE项目中使用,更重要的是在web项目中使用时,他会自动将HttpServerletSession自动整合到自己的session,让你直接可以在Shiro的session中拿到你放在HttpServerletSession中的变量,这在非controller组件中非常有用
*/
Session session = currentUser.getSession();
// 在session中放置变量
session.setAttribute("someKey", "aValue");
// 从session中取出变量
String value = (String) session.getAttribute("someKey");
if (value.equals("aValue")) {
log.info("Retrieved the correct value! [" + value + "]");
}
// 判断用户(Subject)是否经过授权(登录)
if (!currentUser.isAuthenticated()) {
// 如果未登录,创建包含用户名及密码的认证令牌:用户名,密码
UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa");
// 设置记住我标识,如果该标识为true,对于运行记住我访问的资源,不用经过登录认证即可访问
token.setRememberMe(true);
try {
// Subject认证授权
currentUser.login(token);
} catch (UnknownAccountException uae) {
// 用户名未知
log.info("There is no user with username of " + token.getPrincipal());
} 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 (AuthenticationException ae) {
// 其他认证错误,AuthenticationException为其他认证异常的父类
}
} //say who they are:
//print their identifying principal (in this case, a username):
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.");
} // 判断用户是否拥有lightsaber:wield权限
if (currentUser.isPermitted("lightsaber:wield")) {
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("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!");
} // 用户退出登录
currentUser.logout(); System.exit(0);
}

shiro入门笔记之第一个demo创建的更多相关文章

  1. GIT入门笔记(18)- 标签创建和管理

    git tag <name>用于新建一个标签,默认为HEAD,也可以指定一个commit id: git tag -a <tagname> -m "blablabla ...

  2. GIT入门笔记(16)- 分支创建和管理

    查看分支:git branch创建分支:git branch <name>切换分支:git checkout <name>创建+切换分支:git checkout -b < ...

  3. Cocos2dx游戏开发系列笔记13:一个横版拳击游戏Demo完结篇

    懒骨头(http://blog.csdn.net/iamlazybone QQ:124774397 ) 写下这些东西的同时 旁边放了两部电影 周星驰的<还魂夜> 甄子丹的<特殊身份& ...

  4. JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识

    JAVA WEB快速入门系列之前的相关文章如下:(文章全部本人[梦在旅途原创],文中内容可能部份图片.代码参照网上资源) 第一篇:JAVA WEB快速入门之环境搭建 第二篇:JAVA WEB快速入门之 ...

  5. (1)shiro简介和第一个demo

    之前一直在用shiro开发,不过只是会使用,并没有深入了解,最近有时间学习了一下,把最近学习所得分享一下. shiro简介 Apache Shiro是一个强大且易用的Java安全框架,执行身份验证.授 ...

  6. Apcahe Shiro学习笔记(一):简介及运行官方Demo

    一.Apache Shrio: apache shiro 是一个功能强大和易于使用的Java安全框架,为开发人员提供一个直观而全面的的解决方案的认证,授权,加密,会话管理. 支持认证跨一个或多个数据源 ...

  7. Cocos2d-x 学习(1)—— 通过Cocos Studio创建第一个Demo

    近期在工作上有了比較大的转变,自学情绪也慢慢高涨,本来一直在研究unity的技术.由于换了工作会開始接触cocos2d-x.但并不意味着停止研究unity,以后有时间还是会继续的. 公司的cocos2 ...

  8. webpack快速入门——webpack3.X 快速上手一个Demo

    1.进入根目录,建两个文件夹,分别为src和dist 1).src文件夹:用来存放我们编写的javascript代码,可以简单的理解为用JavaScript编写的模块. 2).dist文件夹:用来存放 ...

  9. 【Asp.net入门07】第一个ASP.NET 应用程序-创建数据模型和存储库

    1.理解概念 先理解一下两个概念. 模型 模型是指数据的结构类型,以及可调用的方法.对面向对象编程方法来说,其实就是类.模型类就是一个描述数据的类.只有把数据按一定方式描述出来,我们才能在程序中方便地 ...

随机推荐

  1. 【硬盘】RAID

    RAID是英文Redundant Array of Independent Disks(独立磁盘冗余阵列),简称磁盘阵列.下面将各个级别的RAID介绍如下. 一.为什么使用Raid? 1.对磁盘高速存 ...

  2. Codeforces 789e The Great Mixing (bitset dp 数学)

    Sasha and Kolya decided to get drunk with Coke, again. This time they have k types of Coke. i-th typ ...

  3. UVa 839 Not so Mobile (递归思想处理树)

    Before being an ubiquous communications gadget, a mobilewas just a structure made of strings and wir ...

  4. 大碗宽面Alpha冲刺阶段博客目录

    大碗宽面Alpha冲刺阶段博客目录 一.Scrum Meeting 1. [第六周会议记录]第六周链接 2. [第七周会议记录]第七周链接 二.测试报告 [alpha阶段测试报告](博客链接) ## ...

  5. restTemplate源码详解深入剖析底层实现思路

    一 准备工作 1 启动一个项目,发布一个restful的get请求,端口设置为8090. @RestController @RequestMapping("/youku1327") ...

  6. jpql简单l查询

    JPQL全称Java Persistence Query Language package com.ytkj.entity; import javax.persistence.*; import ja ...

  7. leetcode python反转字符串中的单词

    # Leetcode 557 反转字符串中的单词III### 题目描述 给定一个字符串,你需要反转字符串中每个单词的字符顺序,同时仍保留空格和单词的初始顺序. **示例1:** 输入: "L ...

  8. 通往大神之路,百度Java面试题前200页。

    基本概念 操作系统中 heap 和 stack 的区别 什么是基于注解的切面实现 什么是 对象/关系 映射集成模块 什么是 Java 的反射机制 什么是 ACID BS与CS的联系与区别 Cookie ...

  9. python调用tushare获取沪深A股票资金流向数据

    接口:moneyflow 描述:获取沪深A股票资金流向数据,分析大单小单成交情况,用于判别资金动向 限量:单次最大提取4000行记录,总量不限制 积分:用户需要至少1500积分才可以调取,基础积分有流 ...

  10. docker--image的获取

    image有几种获取方式: 1.Docker官方提供了一种文件格式:Dockerfile,通过这种格式的文件,我们可以定义一个image,然后通过Dockerfile我们可以构建(build)一个im ...