2019独角兽企业重金招聘Python工程师标准>>>

1.10分钟带你轻松入门shiro

Shiro是apache旗下的一款轻量级的Java安全框架,它可以提供如下服务:

  • Authentication(认证)

  • Authorization(授权)

  • Session Management(会话管理)

  • Cryptography(加密)

接下来我们来一起进入shiro的世界吧

第一步: 在pom.xml文件中添加以下依赖:

<!-- Shiro -->
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.2.3</version>
</dependency>

第二步: 在classpath文件下添加shiro.ini文件:

[users]
shiro = 201314

第三步:认识一下shiro的认证服务,写一个main方法测试一下:

package com.simple.shiro;import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;/*** @author xiaobianchen* @version 1.0 2016/4/19*/
public class HelloShiro {private static final Logger logger = Logger.getLogger(HelloShiro.class);public static void main(String[] args) {Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");SecurityManager securityManager = factory.getInstance();SecurityUtils.setSecurityManager(securityManager);//获取当前用户Subject currentUser = SecurityUtils.getSubject();//登录UsernamePasswordToken token = new UsernamePasswordToken("shiro", "201314");try {currentUser.login(token);} catch (AuthenticationException e) {logger.info("login failure!");return;}logger.info("login success! Hello  " + currentUser.getPrincipal());//注销currentUser.logout();}
}

我们分析一下这个 HelloShiro 吧:

  1. 需要读取 classpath 下的 shiro.ini 配置文件,并通过工厂类创建 SecurityManager 对象,最终将其放入 SecurityUtils 中,供 Shiro 框架随时获取。

  2. 同样通过 SecurityUtils 类获取 Subject 对象,其实就是当前用户,只不过在 Shiro 的世界里优雅地将其称为 Subject(主体)。

  3. 首先使用一个 Username 与 Password,来创建一个 UsernamePasswordToken 对象,然后我们通过这个 Token 对象调用 Subject 对象的 login 方法,让 Shiro 进行用户身份认证。

  4. 当登录失败时,您可以使用 AuthenticationException 来捕获这个异常;当登录成功时,您可以调用 Subject 对象的 getPrincipal 方法来获取 Username,此时 Shiro 已经为您创建了一个 Session。

  5. 最后还是通过 Subject 对象的 logout 方法来注销本次 Session。

shiro的内部调用流程如下:

2.Web开发中使用shiro

Shiro官方提供的Web模块-shiro-web

你只需要在pom.xml文件中添加如下配置:

<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-web</artifactId><version>1.2.3</version>
</dependency>

然后在web.xml文件中添加Listener与一个Filter

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaeehttp://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"version="3.0"><listener><listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class></listener><filter><filter-name>ShiroFilter</filter-name><filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class></filter><filter-mapping><filter-name>ShiroFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping></web-app>

EnvironmentLoaderListener这个监听器是用来初始化SecurityManager的,并且通过ShiroFilter来完成验证和授权的

在数据库中建立如下面的表

在shiro.ini配置:

[main]
authc.loginUrl=/loginds = org.apache.commons.dbcp.BasicDataSource
ds.driverClassName = com.mysql.jdbc.Driver
ds.url = jdbc:mysql://localhost:3306/test
ds.username = root
ds.password = rootpasswordMatcher = org.apache.shiro.authc.credential.PasswordMatcherjdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.dataSource = $ds
jdbcRealm.authenticationQuery = select password from user where username = ?
jdbcRealm.userRolesQuery = select r.role_name from user u, user_role ur, role r where u.id = ur.user_id and r.id = ur.role_id and u.username = ?
jdbcRealm.permissionsQuery = select p.permission_name from role r, role_permission rp, permission p where r.id = rp.role_id and p.id = rp.permission_id and r.role_name = ?
jdbcRealm.permissionsLookupEnabled = true
jdbcRealm.credentialsMatcher = $passwordMatcher
securityManager.realms = $jdbcRealmcacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
securityManager.cacheManager = $cacheManager[urls]
/ = anon
/space/** = authc

对以上配置解释如下:

首先,在 [main] 片段中,我们定义了一个“authc.loginUrl=/login”,用于配置当需要认证时需要跳转的 URL 地址,这里表示重定向到 /login 请求,通过 Servlet 映射后可定位到 login 页面。

然后,定义了一个 DBCP 的 DataSource,用于获取 JDBC 数据库连接。

然后,定义 JdbcRealm 并指定 DataSource,通过配置以下几条 SQL 来完成认证与授权:

  • authenticationQuery:该 SQL 语句用于提供身份认证,即通过 username 查询 password。

  • userRolesQuery:该 SQL 语句用于提供基于角色的授权验证(属于粗粒度级别),即通过 username 查询 role_name。

  • permissionQuery:该 SQL 语句用于提供基于权限的授权验证(属于细粒度级别),即通过 role_name 查询 permission_name,此时需要开启 permissionsLookupEnabled 开关,默认是关闭的。

最后,在 [urls] 片段中,我们定义了一系列的 URL 过滤规则,Shiro 已经提供了一些默认的 Filter(过滤器),便于我们随时使用,当然您也可以扩展其它的过滤器。就本例配置而言,解释如下:

  • / = anon:对于“/”请求(首页)可以匿名访问的。

  • /space/** = authc:对于以“/space/”开头的请求,均由 authc 过滤器处理,也就是完成身份认证操作。

  • 每次认证都需要与数据库打交道,所以基于性能的考虑 在这里我们配置了cacheManager

那么对于我们新建一个index.jsp页面

<%@ page pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<html>
<head><title>首页</title>
</head>
<body><h1>首页</h1><shiro:guest><p>身份:游客</p><a href="<c:url value="/login"/>">登录</a><a href="<c:url value="/register"/>">注册</a>
</shiro:guest><shiro:user><p>身份:<shiro:principal/></p><a href="<c:url value="/space"/>">空间</a><a href="<c:url value="/logout"/>">退出</a>
</shiro:user></body>
</html>

基于servlet服务器的代码:

@WebServlet("/login")
public class LoginServlet extends HttpServlet {private UserService userService = new UserServiceImpl();@Overridepublic void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 获取表单数据String username = request.getParameter("username");String password = request.getParameter("password");boolean isRememberMe = request.getParameter("rememberMe") != null;// 调用登录服务try {userService.login(username, password, isRememberMe);} catch (LoginException e) {request.setAttribute("exception", e.getName());return;}// 重定向到空间页面response.redirect("/index")}
}

关于shiro-web目前就介绍这么多了

3.Spring与shiro的集成

spring与shiro的集成 首先需要在pom.xml中添加依赖:

<!-- Shiro Spring-->
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.2.3</version>
</dependency>

web.xml中做如下配置:

<web-app id="WebApp_ID" version="2.4"xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/j2eehttp://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"><!-- 读取配置文件 --><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:conf/spring-mybatis.xmlclasspath:conf/spring-shiro.xml</param-value></context-param><!--字符集过滤器--><filter><filter-name>characterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class><init-param><param-name>encoding</param-name><param-value>UTF-8</param-value></init-param><init-param><param-name>forceEncoding</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>characterEncodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><listener><listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class></listener><filter><filter-name>ShiroFilter</filter-name><filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class></filter><filter-mapping><filter-name>ShiroFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><!-- 配置监听器 --><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!--springmvc 核心配置--><servlet><servlet-name>mvc-dispatcher</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><description>SpringContext</description><param-name>contextConfigLocation</param-name><param-value>classpath:conf/mvc-dispatcher-servlet.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>mvc-dispatcher</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!-- 配置主页 --><welcome-file-list><welcome-file>/WEB-INF/jsp/login.jsp</welcome-file></welcome-file-list><!-- 配置session超时时间,单位分钟 --><session-config><session-timeout>30</session-timeout></session-config><!--配置错误页面--><error-page><error-code>404</error-code><location>/WEB-INF/jsp/error/404.jsp</location></error-page></web-app>

最重要的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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager"/><property name="loginUrl" value="/login"/><property name="filterChainDefinitions"><value>/ = anon/space/** = authc</value></property></bean><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><property name="realm" ref="jdbcRealm"/><property name="cacheManager" ref="cacheManager"/></bean><bean id="jdbcRealm" class="org.apache.shiro.realm.jdbc.JdbcRealm"><property name="dataSource" ref="dataSource"/><property name="authenticationQuery" value="select password from user where username = ?"/><property name="userRolesQuery" value="select r.role_name from user u, user_role ur, role r where u.id = ur.user_id and r.id = ur.role_id and u.username = ?"/><property name="permissionsQuery" value="select p.permission_name from role r, role_permission rp, permission p where r.id = rp.role_id and p.id = rp.permission_id and r.role_name = ?"/><property name="permissionsLookupEnabled" value="true"/><property name="cacheManager" ref="cacheManager"/><property name="credentialsMatcher" ref="passwordMatcher"/></bean><bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/><!--缓存--><bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager"/><!--密码加密--><bean id="passwordMatcher" class="org.apache.shiro.authc.credential.PasswordMatcher"/><bean id="passwordService" class="org.apache.shiro.authc.credential.DefaultPasswordService"/></beans>

登录页面建一个jsp页面:

<%@ page pageEncoding="UTF-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<html>
<head><title>登录</title>
</head>
<body><h1><a href="<c:url value="/"/>">首页</a> - 登录</h1><shiro:notAuthenticated><form action="<c:url value="/signIn"/>" method="post"><table><tr><td>用户名:</td><td><input type="text" name="username"/></td></tr><tr><td>密码:</td><td><input type="password" name="password"/></td></tr><tr><td></td><td><label><input type="checkbox" name="rememberMe"/>记住我</label></td></tr><tr><td></td><td><button type="submit">登录</button></td></tr></table></form><c:if test="${requestScope['exception'] == 'LoginException'}"><p>登录失败!</p></c:if>
</shiro:notAuthenticated><shiro:authenticated><c:redirect url="/space"/>
</shiro:authenticated></body>
</html>

控制器层:

@Controller
public class LoginController {private static final Logger LOG = LoggerFactory.getLogger(LoginController.class);@RequestMapping(value = "/index",method = RequestMethod.GET)public String index(){return "index";}@Autowiredprivate IUserService userService;@RequestMapping(value = "/signIn",method = RequestMethod.GET)public String signIn(){return "signIn";}@RequestMapping(value = "/signIn",method = RequestMethod.POST)public String submit(HttpServletRequest request) {// 获取表单数据String username = request.getParameter("username");String password = request.getParameter("password");boolean isRememberMe = request.getParameter("rememberMe") != null;// 调用登录服务try {userService.login(username, password);} catch (LoginException e) {request.setAttribute("exception", e.getName());return signIn();}// 重定向到主页面return "redirect:/index";}
}

转载于:https://my.oschina.net/chenxiaobian/blog/660164

轻松带你走进shiro的世界相关推荐

  1. 【密码学】一万字带您走进密码学的世界(上)

    引文 密码学是研究编制密码和破译密码的技术科学.研究密码变化的客观规律,应用于编制密码以保守通信秘密的,称为编码学:应用于破译密码以获取通信情报的,称为破译学,总称密码学. 为了使读者对密码学有一个整 ...

  2. 【密码学】一万字带您走进密码学的世界(下)

    引文 密码学是研究编制密码和破译密码的技术科学.研究密码变化的客观规律,应用于编制密码以保守通信秘密的,称为编码学:应用于破译密码以获取通信情报的,称为破译学,总称密码学. 在<一万字带您走进密 ...

  3. 带你走进rsync的世界

    导读 Rsync(remote synchronize)是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件,也可以使用 Rsync 同步本地硬盘中的不同目录.rsync共有3种使用方 ...

  4. 冷链冷库|果蔬保鲜储藏冷链冷库 海格里斯带你走进果蔬冷库世界

    冷链行业涵盖冷冻加工,冷藏贮藏,冷链运输和冷链销售全过程.冷链行业的主要设施包括冷库或低温物流中心.生鲜食品加工中心(包括中央厨房).冷藏运输车.超市陈列柜等.而冷链行业景气度的提升则会带动冷库,冷藏 ...

  5. vLive带你走进虚拟直播世界

    虚拟直播是什么? 虚拟直播是基于5G+实时渲染技术,在绿幕环境下拍摄画面,通过实时抠像.渲染与合成,再推流到直播平台的一种直播技术.尽管这种技术早已被影视工业所采用,但在全民化进程中却是困难重重,面临 ...

  6. 带你走进服务器的世界看个明白

    第1章 如何学习Linux 要想学好任何一门学问,不仅要眼睛看,耳朵听 还要动手记,勤思考,多交流甚至尝试着去教会别人 第2章 服务器 2.1 运维的基本职责: 网站的数据不能丢 网站7*24小时运行 ...

  7. 【Java】带你走进Debug的世界

    关于Debug和本文 Debug,意为"调试",是程序员必备技能之一. Debug开始用的时候还是很不习惯的,需要适应,本文面向新手介绍Debug相关内容. Debug的三种手段 ...

  8. 韩钰带你走进电商世界之如何成功运营一家淘宝C店详细方案

    一:店铺运营的八个步骤 第一步:寻宝贝 选品是运营的第一步,后续的运营工作都是以商品为载体,以挖掘市场潜力商品,帮助提升宝贝效果,优化库存状况,监控热销单品,跟踪竞争对手,打造爆款为运营主要目标. 行 ...

  9. Java基础教程带你走进java的世界

    Java教程 Java简介 什么是Java? Java是由Sun Microsystems公司于1995年5月推出的Java面向对象程序设计语言和Java平台的总称. Java分为三个体系: Java ...

最新文章

  1. NLP实战:利用Python理解、分析和生成文本 | 赠书
  2. [CF843D]Dynamic Shortest Path
  3. 时序图、活动图、状态图、协作图的区别
  4. 关于matlab的单精度与双精度
  5. C++中函数调用操作符的重载
  6. c#获取本地ip地址网关子网掩码_教你如何修改路由器LAN口IP地址的方法
  7. 国内网络安全这门行业人才会不会饱和呢?
  8. 蝉联IDC机器学习平台市场No.1 第四范式市场领先优势持续扩大
  9. linux系统性能监视高级命令(12个)
  10. 软考网络工程师学习笔记4-局域网与城域网
  11. android缩放动画后,Android ObjectAnimator:缩放后动画填充
  12. dcmtk 3.6.0 error C1083: Cannot open include file: 'iostream.h' 解决办法
  13. django学习笔记:AdminSite界面配置
  14. Android权威编程指南读书笔记(1-2章)
  15. linux scp 拷贝文件
  16. 基于SSH 实验室设备管理系统详细功能
  17. html中用于超链接的标签,html中,超链接用的是什么标签
  18. 2021迅雷web实习生面试经验
  19. Appium从环境搭建到测试脚本编写(四)
  20. JAVA转go系列之我为什么要学习GO

热门文章

  1. python ubuntu18.04 sublime_Ubuntu下Sublime配置python编译环境及新手使用指导:
  2. iTerm2、Oh My Zsh、主题等
  3. php怎么给接口里的方法传参,PHP接口中方法的参数和实现类方法中的参数可以不一致的问题...
  4. Golang开发的跨平台蜜罐平台HFish v0.6.4源码
  5. 公布一个简单的日志记录方法 【转】-要研究
  6. 通过IHttpHandlerFactory,过滤TextBox、Input和Textarea中的特殊字符
  7. html5游戏制作入门系列教程(二)
  8. 常用JavaScript函数 71 -(自我总结)
  9. 博弈——威佐夫博弈(hdu1527,2177)
  10. Linux开启路由转发功能