本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云
Shiro提供了与Web集成的支持,其通过一个ShiroFilter入口来拦截需要安全控制的URL,然后进行相应的控制,ShiroFilter类似于如Strut2/SpringMVC这种web框架的前端控制器,其是安全控制的入口点,其负责读取配置(如ini配置文件),然后判断URL是否需要登录/权限等工作。
本文涉及的源代码下载链接:http://pan.baidu.com/s/1qYjREsk 密码:negu
创建 Maven web工程
由于是web 工程,因此需要tomcat 或 jetty 作为容器。此处我们使用了jetty-maven-plugin和tomcat7-maven-plugin插件;这样可以直接使用“mvn jetty:run”或“mvn tomcat7:run”直接运行webapp了。然后通过URL http://localhost:8080/shiro/访问即可。有不会maven 的可以先学习 maven 教程。
另外我们还需要 servlet 和 shiro-web 的依赖,添加pom配置。
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.2.2</version> </dependency>
其他依赖请参考源码的pom.xml。限于篇幅我这里就不一一列举了。
web.xml 配置shiro
<filter> <filter-name>iniShiroFilter</filter-name> <filter-class>org.apache.shiro.web.servlet.IniShiroFilter</filter-class> <init-param> <param-name>configPath</param-name> <param-value>classpath:shiro.ini</param-value> </init-param> </filter> <filter-mapping> <filter-name>iniShiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
- 使用IniShiroFilter作为Shiro安全控制的入口点,通过url-pattern指定需要安全的URL;
- 通过configPath指定ini配置文件位置,默认是先从/WEB-INF/shiro.ini加载,如果没有就默认加载classpath:shiro.ini,即默认相对于web应用上下文根路径;
- 也可以通过如下方式直接内嵌ini配置文件内容到web.xml
<init-param> <param-name>config</param-name> <param-value> ini配置文件贴在这 </param-value> </init-param>
源代码中列举了两个版本的shiro配置,这里只举例了一种,另外一种略过。
Shiro 与Spring集成
<filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <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>
DelegatingFilterProxy作用是自动到spring容器查找名字为shiroFilter(filter-name)的bean并把所有Filter的操作委托给它。然后将ShiroFilter配置到spring容器即可:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <!—忽略其他,详见与Spring集成部分 --> </bean>
Shiro 的[urls] 配置
[urls]部分的配置,其格式是: “url=拦截器[参数],拦截器[参数]”;即如果当前请求的url匹配[urls]部分的某个url模式,将会执行其配置的拦截器。比如anon拦截器表示匿名访问(即不需要登录即可访问);authc拦截器表示需要身份认证通过后才能访问;roles[admin]拦截器表示需要有admin角色授权才能访问;而perms[“user:create”]拦截器表示需要有“user:create”权限才能访问。shiro.ini配置部分见案例源码。
url模式使用Ant风格模式
Ant路径通配符支持?、*、**,注意通配符匹配不包括目录分隔符“/”:
?:匹配一个字符,如”/admin?”将匹配/admin1,但不匹配/admin或/admin2;
*:匹配零个或多个字符串,如/admin*将匹配/admin、/admin123,但不匹配/admin/1;
**:匹配路径中的零个或多个路径,如/admin/**将匹配/admin/a或/admin/a/b。
url模式匹配顺序是按照在配置中的声明顺序匹配,即从头开始使用第一个匹配的url模式对应的拦截器链。如:
/bb/**=filter1 /bb/aa=filter2 /**=filter3
如果请求的url是“/bb/aa”,因为按照声明顺序进行匹配,那么将使用filter1进行拦截。
登录 Servlet 实现
@WebServlet(name = "loginServlet", urlPatterns = "/login") public class LoginServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { req.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String error = null; String username = req.getParameter("username"); String password = req.getParameter("password"); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { subject.login(token); } catch (UnknownAccountException e) { error = "用户名/密码错误"; } catch (IncorrectCredentialsException e) { error = "用户名/密码错误"; } catch (AuthenticationException e) { //其他错误,比如锁定,如果想单独处理请单独catch处理 error = "其他错误:" + e.getMessage(); } if(error != null) {//出错了,返回登录页面 req.setAttribute("error", error); req.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(req, resp); } else {//登录成功 req.getRequestDispatcher("/WEB-INF/jsp/loginSuccess.jsp").forward(req, resp); } } }
doPost时进行登录,登录时收集username/password参数,然后提交给Subject进行登录。如果有错误再返回到登录页面;否则跳转到登录成功页面(此处应该返回到访问登录页面之前的那个页面,或者没有上一个页面时访问主页)。
基于Basic的拦截器身份验证
shiro-basicfilterlogin.ini配置如下:
[main] authcBasic.applicationName=please login perms.unauthorizedUrl=/unauthorized roles.unauthorizedUrl=/unauthorized [users] xttblog=123,admin codedq=123 [roles] admin=user:*,menu:* [urls] /role=authcBasic,roles[admin]
authcBasic是org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter类型的实例,其用于实现基于Basic的身份验证;applicationName用于弹出的登录框显示信息使用,如下图所示:
[urls]部分配置了/role地址需要走authcBasic拦截器,即如果访问/role时还没有通过身份验证那么将弹出如上图的对话框进行登录,登录成功即可访问。另外需要把shiroConfigLocations改为shiro-basicfilterlogin.ini。
基于表单的拦截器身份验证
shiro-formfilterlogin.ini配置如下:
[main] authc.loginUrl=/formfilterlogin authc.usernameParam=username authc.passwordParam=password authc.successUrl=/ authc.failureKeyAttribute=shiroLoginFailure perms.unauthorizedUrl=/unauthorized roles.unauthorizedUrl=/unauthorized [users] xttblog=123,admin codedq=123 [roles] admin=user:*,menu:* [urls] /static/**=anon /formfilterlogin=authc /role=authc,roles[admin] /permission=authc,perms["user:create"]
authc是org.apache.shiro.web.filter.authc.FormAuthenticationFilter类型的实例,其用于实现基于表单的身份验证;通过loginUrl指定当身份验证时的登录表单;usernameParam指定登录表单提交的用户名参数名;passwordParam指定登录表单提交的密码参数名;successUrl指定登录成功后重定向的默认地址(默认是“/”)(如果有上一个地址会自动重定向带该地址);failureKeyAttribute指定登录失败时的request属性key(默认shiroLoginFailure);这样可以在登录表单得到该错误key显示相应的错误消息;
同意的需要在web.xml中把shiroConfigLocations改为shiro- formfilterlogin.ini。
其他授权(角色/权限验证)、退出等见项目源码。本文涉及的源代码下载链接:http://pan.baidu.com/s/1qYjREsk 密码:negu
最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!
本文原文出处:业余草: » shiro web 集成案例详解