千家信息网

shiro教程(4)-shiro与项目集成开发

发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,1 shiro与项目集成开发1.1 shiro与spring web项目整合shiro与springweb项目整合在"基于url拦截实现的工程"基础上整合,基于url拦截实现的工程的技术架构是spri
千家信息网最后更新 2026年11月01日shiro教程(4)-shiro与项目集成开发

1 shiro与项目集成开发

1.1 shiro与spring web项目整合

shiro与springweb项目整合在"基于url拦截实现的工程"基础上整合,基于url拦截实现的工程的技术架构是springmvc+mybatis,整合注意两点:

1、shiro与spring整合

2、加入shiro对web应用的支持

1.1.1 取消原springmvc认证和授权拦截器

去掉springmvc.xml中配置的LoginInterceptor和PermissionInterceptor拦截器。

1.1.2 加入shiro的jar包

1.1.3 web.xml添加shiro Filter

[html] view plain copy print?

  1. <filter>

  2. <filter-name>shiroFilterfilter-name>

  3. <filter-class>org.springframework.web.filter.DelegatingFilterProxyfilter-class>

  4. <init-param>

  5. <param-name>targetFilterLifecycleparam-name>

  6. <param-value>trueparam-value>

  7. init-param>

  8. filter>

  9. <filter-mapping>

  10. <filter-name>shiroFilterfilter-name>

  11. <url-pattern>/*url-pattern>

  12. filter-mapping>



1.1.4 applicationContext-shiro.xml

[html] view plain copy print?

  1. <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">

  2. <property name="securityManager" ref="securityManager" />

  3. <property name="loginUrl" value="/login.action" />

  4. <property name="unauthorizedUrl" value="/refuse.jsp" />

  5. <property name="filters">

  6. <map>

  7. <entry key="authc" value-ref="formAuthenticationFilter" />

  8. map>

  9. property>

  10. <property name="filterChainDefinitions">

  11. <value>

  12. /loginsubmit.action = authc

  13. /logout.action = logout

  14. /refuse.jsp = anon

  15. /item/list.action = roles[item],authc

  16. /js/** anon

  17. /p_w_picpaths/** anon

  18. /styles/** anon

  19. /** = user

  20. value>

  21. property>

  22. bean>

  23. <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">

  24. <property name="realm" ref="userRealm" />

  25. bean>

  26. <bean id="userRealm" class="cn.itcast.ssm.realm.CustomRealm1">

  27. bean>

  28. <bean id="formAuthenticationFilter"

  29. class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">

  30. <property name="usernameParam" value="usercode" />

  31. <property name="passwordParam" value="password" />

  32. <property name="loginUrl" value="/loginsubmit.action" />

  33. bean>



securityManager:这个属性是必须的。

loginUrl:没有登录认证的用户请求将跳转到此地址,不是必须的属性,不输入地址的话会自动寻找项目web项目的根目录下的"/login.jsp"页面。

unauthorizedUrl:没有权限默认跳转的页面。

1.1.5 使用shiro注解授权

在springmvc.xml中配置shiro注解支持,可在controller方法中使用shiro注解配置权限:

[html] view plain copy print?

  1. <aop:config proxy-target-class="true">aop:config>

  2. <bean

  3. class="

  4. org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">

  5. <property name="securityManager" ref="securityManager" />

  6. bean>



修改Controller代码,在方法上添加授权注解,如下:

[java] view plain copy print?

  1. // 查询商品列表

  2. @RequestMapping("/queryItem")

  3. @RequiresPermissions("item:query")

  4. public ModelAndView queryItem() throws Exception {



上边代码@RequiresPermissions("item:query")表示必须拥有"item:query"权限方可执行。

其它的方法参考示例添加注解

1.1.6 自定义realm

此realm先不从数据库查询权限数据,当前需要先将shiro整合完成,在上边章节定义的realm基础上修改。

[java] view plain copy print?

  1. public class CustomRealm1 extends AuthorizingRealm {

  2. @Autowired

  3. private SysService sysService;

  4. @Override

  5. public String getName() {

  6. return "customRealm";

  7. }

  8. // 支持什么类型的token

  9. @Override

  10. public boolean supports(AuthenticationToken token) {

  11. return token instanceof UsernamePasswordToken;

  12. }

  13. // 认证

  14. @Override

  15. protected AuthenticationInfo doGetAuthenticationInfo(

  16. AuthenticationToken token) throws AuthenticationException {

  17. // 从token中 获取用户身份信息

  18. String username = (String) token.getPrincipal();

  19. // 拿username从数据库中查询

  20. // ....

  21. // 如果查询不到则返回null

  22. if (!username.equals("zhang")) {// 这里模拟查询不到

  23. return null;

  24. }

  25. // 获取从数据库查询出来的用户密码

  26. String password = "123";// 这里使用静态数据模拟。。

  27. // 根据用户id从数据库取出菜单

  28. //...先用静态数据

  29. List menus = new ArrayList();;

  30. SysPermission sysPermission_1 = new SysPermission();

  31. sysPermission_1.setName("商品管理");

  32. sysPermission_1.setUrl("/item/queryItem.action");

  33. SysPermission sysPermission_2 = new SysPermission();

  34. sysPermission_2.setName("用户管理");

  35. sysPermission_2.setUrl("/user/query.action");

  36. menus.add(sysPermission_1);

  37. menus.add(sysPermission_2);

  38. // 构建用户身体份信息

  39. ActiveUser activeUser = new ActiveUser();

  40. activeUser.setUserid(username);

  41. activeUser.setUsername(username);

  42. activeUser.setUsercode(username);

  43. activeUser.setMenus(menus);

  44. // 返回认证信息由父类AuthenticatingRealm进行认证

  45. SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(

  46. activeUser, password, getName());

  47. return simpleAuthenticationInfo;

  48. }

  49. // 授权

  50. @Override

  51. protected AuthorizationInfo doGetAuthorizationInfo(

  52. PrincipalCollection principals) {

  53. // 获取身份信息

  54. ActiveUser activeUser = (ActiveUser) principals.getPrimaryPrincipal();

  55. //用户id

  56. String userid = activeUser.getUserid();

  57. // 根据用户id从数据库中查询权限数据

  58. // ....这里使用静态数据模拟

  59. List permissions = new ArrayList();

  60. permissions.add("item:query");

  61. permissions.add("item:update");

  62. // 将权限信息封闭为AuthorizationInfo

  63. SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

  64. for (String permission : permissions) {

  65. simpleAuthorizationInfo.addStringPermission(permission);

  66. }

  67. return simpleAuthorizationInfo;

  68. }

  69. }



1.1.7 登录

[java] view plain copy print?

  1. //用户登陆页面

  2. @RequestMapping("/login")

  3. public String login()throws Exception{

  4. return "login";

  5. }

  6. // 用户登陆提交

  7. @RequestMapping("/loginsubmit")

  8. public String loginsubmit(Model model, HttpServletRequest request)

  9. throws Exception {

  10. // shiro在认证过程中出现错误后将异常类路径通过request返回

  11. String exceptionClassName = (String) request

  12. .getAttribute("shiroLoginFailure");

  13. if (UnknownAccountException.class.getName().equals(exceptionClassName)) {

  14. throw new CustomException("账号不存在");

  15. } else if (IncorrectCredentialsException.class.getName().equals(

  16. exceptionClassName)) {

  17. throw new CustomException("用户名/密码错误");

  18. } else{

  19. throw new Exception();//最终在异常处理器生成未知错误

  20. }

  21. }



1.1.8 首页

由于session由shiro管理,需要修改首页的controller方法:

[java] view plain copy print?

  1. //系统首页

  2. @RequestMapping("/first")

  3. public String first(Model model)throws Exception{

  4. //主体

  5. Subject subject = SecurityUtils.getSubject();

  6. //身份

  7. ActiveUser activeUser = (ActiveUser) subject.getPrincipal();

  8. model.addAttribute("activeUser", activeUser);

  9. return "/first";

  10. }



1.1.9 退出

由于使用shiro的sessionManager,不用开发退出功能,使用shiro的logout拦截器即可。

[html] view plain copy print?

  1. /logout.action = logout



1.1.10 无权限refuse.jsp

当用户无操作权限,shiro将跳转到refuse.jsp页面。

参考:applicationContext-shiro.xml

1.2 realm连接数据库

1.2.1 添加凭证匹配器

添加凭证匹配器实现md5加密校验。

修改applicationContext-shiro.xml:

[html] view plain copy print?

  1. <bean id="credentialsMatcher"

  2. class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">

  3. <property name="hashAlgorithmName" value="md5" />

  4. <property name="hashIterations" value="1" />

  5. bean>

  6. <bean id="userRealm" class="cn.itcast.ssm.realm.CustomRealm1">

  7. <property name="credentialsMatcher" ref="credentialsMatcher" />

  8. bean>



1.2.2 realm代码

修改realm代码从数据库中查询用户身份信息和权限信息,将sysService注入realm。

[java] view plain copy print?

  1. public class CustomRealm1 extends AuthorizingRealm {

  2. @Autowired

  3. private SysService sysService;

  4. @Override

  5. public String getName() {

  6. return "customRealm";

  7. }

  8. // 支持什么类型的token

  9. @Override

  10. public boolean supports(AuthenticationToken token) {

  11. return token instanceof UsernamePasswordToken;

  12. }

  13. @Override

  14. protected AuthenticationInfo doGetAuthenticationInfo(

  15. AuthenticationToken token) throws AuthenticationException {

  16. // 从token中获取用户身份

  17. String usercode = (String) token.getPrincipal();

  18. SysUser sysUser = null;

  19. try {

  20. sysUser = sysService.findSysuserByUsercode(usercode);

  21. } catch (Exception e) {

  22. // TODO Auto-generated catch block

  23. e.printStackTrace();

  24. }

  25. // 如果账号不存在

  26. if (sysUser == null) {

  27. throw new UnknownAccountException("账号找不到");

  28. }

  29. // 根据用户id取出菜单

  30. List menus = null;

  31. try {

  32. menus = sysService.findMenuList(sysUser.getId());

  33. } catch (Exception e) {

  34. // TODO Auto-generated catch block

  35. e.printStackTrace();

  36. }

  37. // 用户密码

  38. String password = sysUser.getPassword();

  39. //盐

  40. String salt = sysUser.getSalt();

  41. // 构建用户身体份信息

  42. ActiveUser activeUser = new ActiveUser();

  43. activeUser.setUserid(sysUser.getId());

  44. activeUser.setUsername(sysUser.getUsername());

  45. activeUser.setUsercode(sysUser.getUsercode());

  46. activeUser.setMenus(menus);

  47. SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(

  48. activeUser, password, ByteSource.Util.bytes(salt),getName());

  49. return simpleAuthenticationInfo;

  50. }

  51. @Override

  52. protected AuthorizationInfo doGetAuthorizationInfo(

  53. PrincipalCollection principals) {

  54. //身份信息

  55. ActiveUser activeUser = (ActiveUser) principals.getPrimaryPrincipal();

  56. //用户id

  57. String userid = activeUser.getUserid();

  58. //获取用户权限

  59. List permissions = null;

  60. try {

  61. permissions = sysService.findSysPermissionList(userid);

  62. } catch (Exception e) {

  63. // TODO Auto-generated catch block

  64. e.printStackTrace();

  65. }

  66. //构建shiro授权信息

  67. SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

  68. for(SysPermission sysPermission:permissions){

  69. simpleAuthorizationInfo.addStringPermission(sysPermission.getPercode());

  70. }

  71. return simpleAuthorizationInfo;

  72. }

  73. }



1.3 缓存

shiro每个授权都会通过realm获取权限信息,为了提高访问速度需要添加缓存,第一次从realm中读取权限数据,之后不再读取,这里Shiro和Ehcache整合。

1.3.1 添加Ehcache的jar包

1.3.2 配置

在applicationContext-shiro.xml中配置缓存管理器。

[html] view plain copy print?

  1. <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">

  2. <property name="realm" ref="userRealm" />

  3. <property name="sessionManager" ref="sessionManager" />

  4. <property name="cacheManager" ref="cacheManager"/>

  5. bean>

  6. <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">

  7. bean>



1.4 session管理

在applicationContext-shiro.xml中配置sessionManager:

[html] view plain copy print?

  1. <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">

  2. <property name="realm" ref="userRealm" />

  3. <property name="sessionManager" ref="sessionManager" />

  4. bean>

  5. <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">

  6. <property name="globalSessionTimeout" value="600000"/>

  7. <property name="deleteInvalidSessions" value="true"/>

  8. bean>



1.5 验证码

1.5.1 自定义FormAuthenticationFilter

需要在验证账号和名称之前校验验证码。

[java] view plain copy print?

  1. public class MyFormAuthenticationFilter extends FormAuthenticationFilter {

  2. protected boolean onAccessDenied(ServletRequest request,

  3. ServletResponse response, Object mappedValue) throws Exception {

  4. // 校验验证码

  5. // 从session获取正确的验证码

  6. HttpSession session = ((HttpServletRequest)request).getSession();

  7. //页面输入的验证码

  8. String randomcode = request.getParameter("randomcode");

  9. //从session中取出验证码

  10. String validateCode = (String) session.getAttribute("validateCode");

  11. if (!randomcode.equals(validateCode)) {

  12. // randomCodeError表示验证码错误

  13. request.setAttribute("shiroLoginFailure", "randomCodeError");

  14. //拒绝访问,不再校验账号和密码

  15. return true;

  16. }

  17. return super.onAccessDenied(request, response, mappedValue);

  18. }

  19. }



1.5.2 修改FormAuthenticationFilter配置

修改applicationContext-shiro.xml中对FormAuthenticationFilter的配置。

[html] view plain copy print?

  1. <bean id="formAuthenticationFilter"

  2. class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">

  3. 改为

  4. <bean id="formAuthenticationFilter"

  5. class="cn.itcast.ssm.shiro.MyFormAuthenticationFilter">



1.5.3 登陆页面

添加验证码:

[html] view plain copy print?

  1. <TR>

  2. <TD>验证码:TD>

  3. <TD><input id="randomcode" name="randomcode" size="8" /> <img

  4. id="randomcode_img" src="${baseurl}validatecode.jsp" alt=""

  5. width="56" height="20" align='absMiddle' /> <a

  6. href=javascript:randomcode_refresh()>刷新a>TD>

  7. TR>



1.5.4 配置validatecode.jsp匿名访问

修改applicationContext-shiro.xml:

1.6 记住我

用户登陆选择"自动登陆"本次登陆成功会向cookie写身份信息,下次登陆从cookie中取出身份信息实现自动登陆。

1.6.1 用户身份实现java.io.Serializable接口

向cookie记录身份信息需要用户身份信息对象实现序列化接口,如下:

1.6.2 配置

[html] view plain copy print?

  1. <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">

  2. <property name="realm" ref="userRealm" />

  3. <property name="sessionManager" ref="sessionManager" />

  4. <property name="cacheManager" ref="cacheManager"/>

  5. <property name="rememberMeManager" ref="rememberMeManager"/>

  6. bean>

  7. <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">

  8. <property name="cookie" ref="rememberMeCookie" />

  9. bean>

  10. <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">

  11. <constructor-arg value="rememberMe" />

  12. <property name="maxAge" value="2592000" />

  13. bean>


修改formAuthenticationFitler添加页面中"记住我checkbox"的input名称:

[html] view plain copy print?

  1. <bean id="formAuthenticationFilter"

  2. class="cn.itcast.ssm.shiro.MyFormAuthenticationFilter">

  3. <property name="usernameParam" value="usercode" />

  4. <property name="passwordParam" value="password" />

  5. <property name="rememberMeParam" value="rememberMe"/>

  6. <property name="loginUrl" value="/loginsubmit.action" />

  7. bean>



1.6.3 登陆页面

在login.jsp中添加"记住我"checkbox。

[html] view plain copy print?

  1. <TR>

  2. <TD>TD>

  3. <TD>

  4. <input type="checkbox" name="rememberMe" />自动登陆

  5. TD>

  6. TR>



2 附:

2.1 shiro过虑器

过滤器简称

对应的Java类

anon

org.apache.shiro.web.filter.authc.AnonymousFilter

authc

org.apache.shiro.web.filter.authc.FormAuthenticationFilter

authcBasic

org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter

perms

org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter

port

org.apache.shiro.web.filter.authz.PortFilter

rest

org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter

roles

org.apache.shiro.web.filter.authz.RolesAuthorizationFilter

ssl

org.apache.shiro.web.filter.authz.SslFilter

user

org.apache.shiro.web.filter.authc.UserFilter

logout

org.apache.shiro.web.filter.authc.LogoutFilter

anon:例子/admins/**=anon 没有参数,表示可以匿名使用。

authc:例如/admins/user/**=authc表示需要认证(登录)才能使用,没有参数

roles:例子/admins/user/**=roles[admin],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如admins/user/**=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。

perms:例子/admins/user/**=perms[user:add:*],参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。

rest:例子/admins/user/**=rest[user],根据请求的方法,相当于/admins/user/**=perms[user:method] ,其中method为post,get,delete等。

port:例子/admins/user/**=port[8081],当请求的url的端口不是8081是跳转到schemal://serverName:8081?queryString,其中schmal是协议http或https等,serverName是你访问的host,8081是url配置里port的端口,queryString

是你访问的url里的?后面的参数。

authcBasic:例如/admins/user/**=authcBasic没有参数表示httpBasic认证

ssl:例子/admins/user/**=ssl没有参数,表示安全的url请求,协议为https

user:例如/admins/user/**=user没有参数表示必须存在用户,当登入操作时不做检查

注:

anon,authcBasic,auchc,user是认证过滤器,

perms,roles,ssl,rest,port是授权过滤器

2.2 shiro的jsp标签

Jsp页面添加:

<%@ tagliburi="http://shiro.apache.org/tags" prefix="shiro" %>

标签名称

标签条件(均是显示标签内容)

登录之后

不在登录状态时

用户在没有RememberMe时

用户在RememberMe时

在有abc或者123角色时

拥有角色abc

没有角色abc

拥有权限资源abc

没有abc权限资源

显示用户身份名称

显示用户身份中的属性值


用户 信息 参数 权限 数据 身份 配置 登陆 验证 页面 认证 查询 数据库 方法 整合 例子 多个 项目 注解 账号 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网科技海报 互联网科技有限公司经营范围 美国互联网科技 杭州互联网科技公司 亿策互联网科技 安徽鑫晟辉互联网科技 时间互联网络科技 无锡溥仪互联网科技有限公司 隆华科技工业互联网 宁波青枫互联网科技有限公司 互联网科技中介 荆州市昕露互联网络科技有限公司 崇明区互联网教育科技售后服务 互联网媒体平台算高科技产业 内蒙古九一互联网科技 普陀区互联网教育科技管理办法 版纳互联网科技选哪家 北京互联网科技类企业分布 河南商务圈互联网科技有限公司 山东亿川互联网科技有限责任公司 互联网科技园 科技和互联网公司 互联网科技财经 成都狮子座互联网科技 厦门千工互联网科技有限公司 上海钢联属于互联网科技股吗 互联网科技年终奖 互联网科技平台产品运营 保山浩联互联网科技有限公司 现代科技的标志之一的互联网
0