springMVC与shiro集成
来源:互联网 发布:中华英才网 知乎 编辑:程序博客网 时间:2024/06/06 03:59
shiro可以跟springMVC很好的集成。
但是对于shiro集成struts2的资料比较少。
容易遇到注解失效等问题。
因为很多老的项目可能用的是Spring+ sturts框架。
如果我们使用shiro跟sturts集成的话 需要用到sturts的注解。
这样其实struts也失去了它跳转配置的便利。
所以 考虑了之后 还是觉得 使用springMVC框架与shiro集成。
我现在有一个spirngMVC的框架,在此基础上进行shiro的添加测试。
权限分析
用户分为两种用户normal,manager,有五个模块:结果查看模块,用户数据生成单选模块,用户数据生成批量模块,用户权限管理模块,操作日志查看模块。
normal用户:
结果查看模块resultlist,
用户数据生成单选模块parseResultUserlist,parseResultAdd,
用户数据生成批量模块parseResultUserlistMulti,parseResultAddMulti
manager用户:
结果查看模块resultlist,
用户数据生成单选模块parseResultUserlist,parseResultAdd,
用户数据生成批量模块parseResultUserlistMulti,parseResultAddMulti,
用户权限管理模块usermanage,
操作日志查看模块。loglist
新建User.class
根据shiro的模型 我们需要给User加上角色role和权限permission。因为我用的mongodb数据库是非关系型的数据库。我们把role和permission直接加在User对象里。
User.java
package com.test.web.support.shiro;import java.util.ArrayList;import java.util.List;import org.apache.shiro.authc.credential.DefaultPasswordService;import org.apache.shiro.authc.credential.PasswordService;import org.apache.shiro.crypto.hash.SimpleHash;import org.apache.shiro.util.ByteSource;import org.springframework.context.ApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext;import com.test.domain.entity.User;import com.test.domain.repository.UserReposity;public class UserAdd {public static void main(String[] args) { final String[] paths = new String[] { "src/main/resource/com/test/web/conf/mongodb/spring-mongodb.xml"}; final ApplicationContext context = new FileSystemXmlApplicationContext( paths); // ClassPathXmlApplicationContext final UserReposity processor = (UserReposity) context .getBean("userReposity"); User user=new User();String username="test";String password="123";user.setUsername(username); String encrypted = new SimpleHash("MD5",password,null,1).toHex(); //这里的加密方式要与配置对应 //<property name="hashAlgorithmName" value="md5"/>指定hash算法为MD5; 无默认值,必须指定为MD5或者SHA-1等 //<property name="hashIterations" value="1"/>指定散列次数为1次;默认为1 // <property name="storedCredentialsHexEncoded" value="true"/>指定Hash散列值使用Hex加密存储。value="false"表明hash散列值用用Base64-encoded存储。默认为true user.setPassword(encrypted); List<String> permissionList=new ArrayList<String>(); List<String> roleList=new ArrayList<String>(); permissionList.add("parseResultAdd"); permissionList.add("parseResultAddMulti"); permissionList.add("resultlist"); roleList.add("normal"); user.setPermissionList(permissionList); user.setRoleList(roleList); processor.saveObject(user);}}
同时在数据库中中添加相关的user数据
我的mongodb数据添加两个用户如下:
{ "_id" : ObjectId("558915caa668aa7b08eb1197"), "_class" : "com.test.domain.entity.User", "username" : "admin", "password" : "202cb962ac59075b964b07152d234b70", "permissionList" : ["parseResultAdd", "parseResultAddMulti", "usermanage", "loglist", "resultlist"], "roleList" : ["admin"]}{ "_id" : ObjectId("55891777a668e496191c6eb1"), "_class" : "com.test.domain.entity.User", "username" : "test", "password" : "202cb962ac59075b964b07152d234b70", "permissionList" : ["parseResultAdd", "parseResultAddMulti", "resultlist"], "roleList" : ["normal"]}
"password" : "202cb962ac59075b964b07152d234b70"对应密码为123。
这里采用了shiro自带的加密方式。详情看下面的代码。
package com.test.web.support.shiro;import java.util.ArrayList;import java.util.List;import org.apache.shiro.authc.credential.DefaultPasswordService;import org.apache.shiro.authc.credential.PasswordService;import org.apache.shiro.crypto.hash.SimpleHash;import org.apache.shiro.util.ByteSource;import org.springframework.context.ApplicationContext;import org.springframework.context.support.FileSystemXmlApplicationContext;import com.test.domain.entity.User;import com.test.domain.repository.UserReposity;public class UserAdd {public static void main(String[] args) { final String[] paths = new String[] { "src/main/resource/com/test/web/conf/mongodb/spring-mongodb.xml"}; final ApplicationContext context = new FileSystemXmlApplicationContext( paths); // ClassPathXmlApplicationContext final UserReposity processor = (UserReposity) context .getBean("userReposity"); User user=new User();String username="admin";String password="123";user.setUsername(username); String encrypted = new SimpleHash("MD5",password,null,1).toHex(); //这里的加密方式要与配置对应 //<property name="hashAlgorithmName" value="md5"/>指定hash算法为MD5; 无默认值,必须指定为MD5或者SHA-1等 //<property name="hashIterations" value="1"/>指定散列次数为1次;默认为1 // <property name="storedCredentialsHexEncoded" value="true"/>指定Hash散列值使用Hex加密存储。value="false"表明hash散列值用用Base64-encoded存储。默认为true user.setPassword(encrypted); List<String> permissionList=new ArrayList<String>(); List<String> roleList=new ArrayList<String>(); permissionList.add("parseResultAdd"); permissionList.add("parseResultAddMulti"); permissionList.add("usermanage"); permissionList.add("loglist"); permissionList.add("resultlist"); roleList.add("admin"); user.setPermissionList(permissionList); user.setRoleList(roleList); processor.saveObject(user);}}
String encrypted = new SimpleHash("MD5",password,null,1).toHex();
使用shiro注册增加用户时的加密方式要与自己的设置想匹配。
spring-shiro.xml中配置为:
<bean id="mongoRealm" class="com.test.web.support.shiro.MyShiro"><property name="credentialsMatcher"><bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"><property name="hashAlgorithmName" value="MD5"></property></bean></property></bean>验证时为:
添加后如图所示:
导入jar
因为我们的是maven工程,所以把shiro相关的包写入pom.xml文件。
在pom.xml中添加
<!--Apache Shiro所需的jar包--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.2.2</version> </dependency>
完整版的pom.xml太长,这里就不给出了,可下载源码查看
配置web.xml
在web.xml里添加shiro 的配置
shiro的filter应该放在struts2的 filter的上面
<!-- Shiro配置 --> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
完整版web.xml
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"version="3.0"><filter><filter-name>encodingFilter</filter-name><filter-class>com.test.web.servlet.filter.EncodingFilter</filter-class></filter><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>encodingFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><filter-mapping><filter-name>shiroFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping><servlet><servlet-name>springMVC</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring-web.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>springMVC</servlet-name><url-pattern>/</url-pattern></servlet-mapping><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><context-param><param-name>contextConfigLocation</param-name><param-value> classpath:spring-web.xml </param-value></context-param><welcome-file-list><welcome-file></welcome-file></welcome-file-list><session-config><cookie-config><name>_sid</name></cookie-config><tracking-mode>COOKIE</tracking-mode></session-config><error-page><error-code>404</error-code><location>/404</location></error-page><error-page><exception-type>javax.servlet.ServletException</exception-type><location>/error</location></error-page><jsp-config><jsp-property-group><url-pattern>*.jsp</url-pattern><page-encoding>UTF-8</page-encoding><scripting-invalid>false</scripting-invalid></jsp-property-group></jsp-config></web-app>
建立dbRelm
主要是扩展AuthorizingRealm, 实现在数据库中查询是否有该帐号密码,实现验证。
我新建一个MyShiro的class
MyShiro.java
package com.test.web.support.shiro;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.SimpleAuthenticationInfo;import org.apache.shiro.authc.UsernamePasswordToken;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.authz.SimpleAuthorizationInfo;import org.apache.shiro.realm.AuthorizingRealm;import org.apache.shiro.subject.PrincipalCollection;import org.springframework.beans.factory.annotation.Autowired;import com.test.domain.entity.User;import com.test.domain.repository.UserReposity;public class MyShiro extends AuthorizingRealm{ @AutowiredUserReposity userReposity; /** * 权限认证 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //获取登录时输入的用户名 String loginName=(String) principalCollection.fromRealm(getName()).iterator().next(); //到数据库查是否有此对象 User user=userReposity.findByName(loginName); if(user!=null){ //权限信息对象info,用来存放查出的用户的所有的角色(role)及权限(permission) SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(); //用户的角色集合 info.addRoles(user.getRoleList()); //用户的角色对应的所有权限,如果只使用角色定义访问权限,下面的一行可以不要 info.addStringPermissions(user.getPermissionList()); return info; } return null; } /** * 登录认证; */ @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken authenticationToken) throws AuthenticationException { //UsernamePasswordToken对象用来存放提交的登录信息 UsernamePasswordToken token=(UsernamePasswordToken) authenticationToken; //查出是否有此用户 User user=userReposity.findByName(token.getUsername()); if(user!=null){ //若存在,将此用户存放到登录认证info中 return new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), getName()); } return null; }}
同时还应配置mongodb的访问xml和userReposity的bean定义,这里不给出了,详情可下载源码
主要有两部分
一是对数据库具体访问的接口实现
二是 spring-mongodb.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" xmlns:context="http://www.springframework.org/schema/context"xmlns:mongo="http://www.springframework.org/schema/data/mongo"xmlns:repository="http://www.springframework.org/schema/data/repository"xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.5.xsd "> <bean id="userReposity" class="com.test.domain.repository.impl.UserReposityImpl"parent="mongoTemplate"></bean><bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongo" ref="mongo" /> <constructor-arg name="databaseName" value="shiro_test"/> </bean> <bean id="mongo" class="org.springframework.data.mongodb.core.MongoFactoryBean"> <property name="host" value="127.0.0.1"/> <property name="port" value="27017"/> </bean> </beans>
新建用于登录,登出,权限跳转的控制HomeController
HomeController.java
package com.test.web.controller;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.UsernamePasswordToken;import org.springframework.ui.Model;import org.springframework.validation.BindingResult;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.servlet.mvc.support.RedirectAttributes;import com.test.domain.entity.User;public class HomeController { @RequestMapping(value="/login",method=RequestMethod.GET) public String loginForm(Model model){ model.addAttribute("user", new User()); return "/login"; } @RequestMapping(value="/login",method=RequestMethod.POST) public String login(User user,BindingResult bindingResult,RedirectAttributes redirectAttributes){ try { if(bindingResult.hasErrors()){ return "/login"; } //使用权限工具进行用户登录,登录成功后跳到shiro配置的successUrl中,与下面的return没什么关系! SecurityUtils.getSubject().login(new UsernamePasswordToken(user.getUsername(), user.getPassword())); return "/home"; } catch (AuthenticationException e) { redirectAttributes.addFlashAttribute("message","用户名或密码错误"); return "redirect:/login"; } } @RequestMapping(value="/logout",method=RequestMethod.GET) public String logout(RedirectAttributes redirectAttributes ){ //使用权限管理工具进行用户的退出,跳出登录,给出提示信息 SecurityUtils.getSubject().logout(); redirectAttributes.addFlashAttribute("message", "您已安全退出"); return "redirect:/login"; } @RequestMapping("/403") public String unauthorizedRole(){ return "/403"; } }
新建登录显示页面
三个页面放在views文件夹中 login.jsp,home.jsp,403.jsp
login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'MyJsp.jsp' starting page</title> </head> <body> <h1>登录页面----${message }</h1> <form:form action="/login" commandName="user" method="post"> 用户名:<form:input path="username"/> <form:errors path="username" cssClass="error"/> <br/> 密 码:<form:password path="password"/> <form:errors path="password" cssClass="error" /> <br/> <form:button name="button">submit</form:button> </form:form> </body> </html>
页面上的commandName的user需要与HomeController中
@RequestMapping(value="/login",method=RequestMethod.GET)
public String loginForm(Model model){
model.addAttribute("user", new User());
return "/login";
}
里的user对应。属性名对应。
home.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>用户列表</title> </head> <body> <h1>${message }</h1> <h1>用户列表--<a href="/user/add">添加用户</a>---<a href="./logout">退出登录</a> </h1> <h2>权限列表----<shiro:principal/>-当前登录用户名 <br></h2> <shiro:authenticated>用户已经登录显示此内容<br></shiro:authenticated> <shiro:hasRole name="admin">admin角色登录显示此内容<br></shiro:hasRole> <shiro:hasRole name="normal">normal角色登录显示此内容<br></shiro:hasRole> <shiro:hasAnyRoles name="normal,admin">**normal or admin 角色用户登录显示此内容**<br></shiro:hasAnyRoles> <shiro:hasPermission name="loglist">loglist权限用户显示此内容<br></shiro:hasPermission> <shiro:lacksPermission name="loglist"> 不具有loglist权限的用户显示此内容 <br></shiro:lacksPermission> <script type="text/javascript" src="http://cdn.staticfile.org/jquery/1.9.1/jquery.min.js"></script> <script> $(function(){ $(".del").click(function(){ var id=$(this).attr("ref"); $.ajax({ type:"delete", url:"/user/del/"+id, success:function(e){ } }); }); }); </script> </body> </html>
403.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>权限错误</title> </head> <body> <h1>对不起,您没有权限请求此连接!</h1> </body> </html>
在Spring中配置
spring-shiro.xml
<?xml version="1.0" encoding="UTF-8"?><!-- ~ 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. --><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"><!--<bean id="iniRealm" class="org.apache.shiro.realm.text.IniRealm"><constructor-arg name="resourcePath"value="classpath:com/test/web/conf/shiro/shiro.ini"></constructor-arg></bean>--> <bean id="mongoRealm" class="com.test.web.support.shiro.MyShiro"><property name="credentialsMatcher"><bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"><property name="hashAlgorithmName" value="MD5"></property></bean></property></bean> <!-- securityManager --><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><property name="rememberMeManager"><bean class="org.apache.shiro.web.mgt.CookieRememberMeManager"><property name="cookie"><bean class="org.apache.shiro.web.servlet.SimpleCookie"><constructor-arg name="name" value="RememberMe" /><property name="maxAge" value="604800" /></bean></property></bean></property><!-- <property name="realm" ref="iniRealm" /> --><property name="realm" ref="mongoRealm" /></bean><!-- shiroFilter --><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager" /><property name="loginUrl" value="/login" /><property name="successUrl" value="/" /><property name="unauthorizedUrl" value="/login" /><property name="filters"><map><entry key="authc"><beanclass="com.test.web.support.shiro.AjaxCompatibleAuthenticationFilter"></bean></entry></map></property><property name="filterChainDefinitions"><value>/login = anon<!-- anon表示此地址不需要任何权限即可访问 --> <!-- /static/**=anon --> <!-- perms[user:query]表示访问此连接需要权限为user:query的用户 --> <!-- /user=perms[user:query] --> <!-- roles[manager]表示访问此连接需要用户的角色为manager --> <!-- /user/add=roles[manager] --> <!-- /user/del/**=roles[admin] --> <!-- /user/edit/**=roles[manager] --> <!--所有的请求(除去配置的静态资源请求或请求地址为anon的请求)都要通过登录验证,如果未登录则跳到/login--> <!-- /** = authc --> </value></property></bean></beans>
这里对页面的访问权限可以相应调节。
结果展示
启动后分别用admin和test账户登录可以看到根据角色和权限已经能显示不同的内容
ps:启用ini配置
realm如果不想用数据库,也可以用文本形式配置,如下
spring-shiro.xml中注释mongoRealm,启用iniRealm
<bean id="iniRealm" class="org.apache.shiro.realm.text.IniRealm"><constructor-arg name="resourcePath"value="classpath:com/test/web/conf/shiro/shiro.ini"></constructor-arg></bean><!-- <bean id="mongoRealm" class="com.test.web.support.shiro.MyShiro"><property name="credentialsMatcher"><bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"><property name="hashAlgorithmName" value="MD5"></property></bean></property></bean> --><!-- securityManager --><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><property name="rememberMeManager"><bean class="org.apache.shiro.web.mgt.CookieRememberMeManager"><property name="cookie"><bean class="org.apache.shiro.web.servlet.SimpleCookie"><constructor-arg name="name" value="RememberMe" /><property name="maxAge" value="604800" /></bean></property></bean></property> <property name="realm" ref="iniRealm" /> <!--<property name="realm" ref="mongoRealm" />--></bean>
新建shiro.ini
shiro.ini 里是帐号密码和角色
[users]admin = 123, admintest = 123, normal[roles]normal= *admin = *当然还可以有其它配置
源码下载:
springshiro
- springMVC与shiro集成
- shiro-入门_1_与springmvc集成
- SpringMVC+Apache Shiro集成
- Springmvc集成Shiro
- shiro讲解之 SpringMVC 集成Shiro
- maven springmvc hibernate shiro 集成
- maven springmvc hibernate shiro 集成
- springmvc集成shiro注解权限
- Shiro集成SpringMVC工程整合
- Shiro集成SpringMVC工程整合
- shiro与spring集成
- shiro 与spring集成
- Shiro与Spring集成
- shiro与spring集成
- shiro与spring集成
- shiro与springMVC整合
- Springmvc集成Shiro实现权限管理
- SpringMVC集成shiro权限(附源码)
- PullToRefresh动态设置刷新的文字
- Android/Java 中利用HttpClient 发送Patch请求,携带Json参数
- 某企业“金融云计算之架构视角”内训圆满结束!
- iOS开发,Reveal的使用
- Android中linux内核模块--开发设备驱动程序 && 上层接口实施 (二)
- springMVC与shiro集成
- 报错error:Error parsing XML:unbound prefix的解决办法
- Error: Error parsing D:\android-sdk-windows\sdk\system-images\android-22\android-wear\x86\devices.xm
- Matt Cutts 称记者说 Google “do no evil” 是找茬儿,应该是 “don't be evil”
- 关键字PASCAL
- 双缓存
- JSongTaste
- crash异常收集
- SAT数学练习题二