相信有很多的程序员,不愿意进行用户管理这块代码实现。

原因之一,不同的JavaEE 系统,用户管理都会有个性化的实现,逻辑很繁琐。

而且是系统门面,以后背锅的几率非常大,可谓是低收益高风险。

最近在系统中集成了 Shiro,感觉这个小家伙还是相当灵活的。

完善的用户认证和授权,干净的API,让人如沐春分。

Apache Shiro 作为一个强大而灵活的开源安全框架,它干净利落地处理身份认证,授权,企业会话管理和加密。

安全有时候是很复杂的,甚至是痛苦的,但它没有必要这样。框架应该尽可能掩盖复杂的地方,露出一个干净而直观的 API。

Apache Shiro 的首要目标是易于使用和理解。

以下是你可以用 Apache Shiro 所做的事情:

a.验证用户来核实他们的身份

b.对用户执行访问控制,如:

c.判断用户是否被分配了一个确定的安全角色。

d.判断用户是否被允许做某事。

e.在任何环境下使用 Session API,即使没有 Web 或 EJB 容器。

f.在身份验证,访问控制期间或在会话的生命周期,对事件作出反应。

g.聚集一个或多个用户安全数据的数据源,并作为一个单一的复合用户“视图”。

h.启用单点登录(SSO)功能。

i.并发登录管理(一个账号多人登录作踢人操作)。

j.为没有关联到登录的用户启用"Remember Me"服务。

以及更多——全部集成到紧密结合的易于使用的 API 中。

目前主流安全框架有 SpringSecurity 和 Shiro,相比于 SpringSecurity,Shiro 轻量化,简单容易上手。

SpringSecurity 太笨重了,难以上手,且只能在 Spring 里用,所以极力推荐Shiro。

本文重点描述集成过程,能让你迅速的将 Shiro 集成到 JavaEE 项目中,毕竟项目都挺紧张的。

1.前戏

Shiro 核心jar:

  1. <!--权限控制 shiro-->
  2. <dependency>
  3. <groupId>org.apache.shiro</groupId>
  4. <artifactId>shiro-spring</artifactId>
  5. <version>${shiro.version}</version>
  6. </dependency>
  7.  
  8. <dependency>
  9. <groupId>org.apache.shiro</groupId>
  10. <artifactId>shiro-ehcache</artifactId>
  11. <version>${shiro.version}</version>
  12. </dependency>

JavaEE 应用开始的地方,web.xml 配置:

  1. <filter>
  2. <filter-name>shiroFilter</filter-name>
  3. <filter-class>
  4. org.springframework.web.filter.DelegatingFilterProxy
  5. </filter-class>
  6. </filter>
  7. <filter-mapping>
  8. <filter-name>shiroFilter</filter-name>
  9. <url-pattern>/*</url-pattern>
  10. </filter-mapping>

Spring-Shiro-context 配置应用启动的使用,会帮助你做很多事情:

  1. <!--Shiro 关键过滤器配置-->
  2. <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
  3. <property name="securityManager" ref="securityManager"/>
  4. <property name="loginUrl" value="/sys/login"/> <!--请求 Url 为 get方式-->
  5. <property name="successUrl" value="/sys/index"/>
  6. <property name="filters">
  7. <map>
  8. <entry key="authc" value-ref="formAuthenticationFilter"/>
  9. </map>
  10. </property>
  11. <property name="filterChainDefinitions" ref="shiroFilterChainDefinitions"/>
  12. </bean>
  13.  
  14. <!-- Shiro 安全管理器 -->
  15. <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
  16. <property name="realm" ref="systemAuthorizingRealm"/>
  17. <property name="cacheManager" ref="shiroCacheManager"/>
  18. </bean>
  19.  
  20. <!--自定义系统认证域-->
  21. <bean id="systemAuthorizingRealm" class="com.rambo.spm.core.shiro.SysAuthorizingRealm"/>
  22.  
  23. <!--shiro ehcache缓存-->
  24. <bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
  25. <property name="cacheManager" ref="cacheManagerFactory"/>
  26. </bean>
  27.  
  28. <!--扩展表单认证过滤器-->
  29. <bean id="formAuthenticationFilter" class="com.rambo.spm.core.shiro.FormAuthenticationFilter"/>
  30.  
  31. <!--权限过滤链定义 -->
  32. <bean name="shiroFilterChainDefinitions" class="java.lang.String">
  33. <constructor-arg>
  34. <value>
  35. /static/** = anon
  36. /captcha-image = anon
  37. /sys/login = authc
  38. /sys/logout = logout
  39. /** =user
  40. </value>
  41. </constructor-arg>
  42. </bean>
  43.  
  44. <!--借助 SpringAOP 扫描那些使用 Shiro 注解的类-->
  45. <aop:config proxy-target-class="true"/>
  46.  
  47. <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
  48. <property name="securityManager" ref="securityManager"/>
  49. </bean>
  50.  
  51. <!--用于在实现了Initializable/Destroyable接口的 Shiro bean 初始化时回调-->
  52. <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>

2.个性化

请求发起的地方一般是前端,不管你是 .jsp/.php/.net.......方式都是类似

  1. <html>
  2. <body>
  3. <h1>login page</h1>
  4. <form id="" action="service/dologin" method="post">
  5. <label>账号:</label><input name="userName" maxLength="40"/>
  6. <input title="是否是管理员" type="checkbox" name="isAdmin"><label>是否为管理员</label><br>
  7. <label>密码:</label><input title="密码" type="password" name="password" /><br>
  8. <input type="submit" value="登录"/>
  9. </form>
  10. <%--用于输入后台返回的验证错误信息 --%>
  11. <P><c:out value="${message }"/></P>
  12. </body>
  13. </html>

自定义项目验证域(验证域可以有多个,已可以有多种方式)。

  1. public class SysAuthorizingRealm extends AuthorizingRealm {
  2. private Log log = LogFactory.get();
  3.  
  4. @Autowired
  5. private SysUserService sysUserService;
  6.  
  7. @Autowired
  8. private SysRoleService sysRoleService;
  9.  
  10. @Autowired
  11. private SysMenuService sysMenuService;
  12.  
  13. /**
  14. * 获取当前用户的认证信息
  15. *
  16. * @param authcToken 携带用户认证所需的信息
  17. * @return 认证结果信息
  18. */
  19. @Override
  20. protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
  21. CaptchaUsernamePasswordToken spmToken = (CaptchaUsernamePasswordToken) authcToken;
  22. log.info("token:{}", ReflectionToStringBuilder.toString(spmToken));
  23.  
  24. SysUser sysUser = sysUserService.getSysUserByLoginName(spmToken.getUsername());
  25. if (sysUser == null) {
  26. return null;
  27. }
  28. byte[] salt = Hex.decode(sysUser.getPasswd().substring(0, 16));
  29. return new SimpleAuthenticationInfo(new SpmPrincipal(sysUser), sysUser.getPasswd().substring(16), ByteSource.Util.bytes(salt), getName());
  30. }
  31.  
  32. /**
  33. * 获取当前用户授权信息
  34. *
  35. * @param principals 该用户身份集合
  36. * @return 当前用户授权信息
  37. */
  38. @Override
  39. protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
  40. SpmPrincipal spmPrincipal = (SpmPrincipal) super.getAvailablePrincipal(principals);
  41. log.info("授权当前:{}", ReflectionToStringBuilder.toString(spmPrincipal));
  42.  
  43. SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
  44.  
  45. List<SysRole> sysRoleList = sysUserService.listSysRoleByUserId(spmPrincipal.getId());
  46. for (SysRole sysRole : sysRoleList) {
  47. info.addRole(sysRole.getRoleType());
  48.  
  49. List<SysMenu> sysMenuList = sysRoleService.listSysMenuByRoleId(sysRole.getUuid());
  50. for (SysMenu sysMenu : sysMenuList) {
  51. info.addStringPermission(sysMenu.getPermisson());
  52. }
  53. }
  54. info.addStringPermission("user");
  55. return info;
  56. }
  57.  
  58. /**
  59. * 设定密码校验的Hash算法与迭代次数
  60. */
  61. @PostConstruct
  62. public void initCredentialsMatcher() {
  63. HashedCredentialsMatcher matcher = new HashedCredentialsMatcher("SHA-1");
  64. matcher.setHashIterations(1024);
  65. setCredentialsMatcher(matcher);
  66. }
  67. }

请求的后台服务,在这里你可以在进行一点业务逻辑

  1. /**
  2. * shiro 登录请求控制,真正的请求由 shiroFilter --> formAuthenticationFilter 进行处理
  3. * 登录成功: 跳转配置的 succssUrl,不触发该方法;
  4. * 登录失败: 触发该方法,可以从扩展的 formAuthenticationFilter 中获取具体的错误信息;
  5. */
  6. @PostMapping("/sys/login")
  7. public Object postSysLogin(HttpServletRequest httpRequest, ModelAndView modelAndView) {
  8. String exceptionName = (String) httpRequest.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);
  9.  
  10. String errorMsg = null;
  11. if (IncorrectCaptchaException.class.getName().equals(exceptionName)) {
  12. errorMsg = "验证码错误!";
  13. } else if (UnknownAccountException.class.getName().equals(exceptionName)) {
  14. errorMsg = "用户不存在!";
  15. } else if (IncorrectCredentialsException.class.getName().equals(exceptionName)) {
  16. errorMsg = "用户或密码错误!";
  17. } else if (exceptionName != null && StrUtil.startWith(exceptionName, "msg:")) {
  18. errorMsg = StrUtil.removeAll(exceptionName, "msg:");
  19. }
  20. return setModelAndView(modelAndView, "sys/sysLogin", errorMsg);
  21. }

整个集成工作就结束了,是不是简单的不要不要的。

等下次项目经理指派你做用户管理的时候,只需要花半天的时间做设计。

借助Shiro 半天时间实现代码。

然后将剩下的时间,做做自己喜欢的其他研究工作。

Spring MVC 急速集成 Shiro 实录的更多相关文章

  1. 细说shiro之五:在spring框架中集成shiro

    官网:https://shiro.apache.org/ 1. 下载在Maven项目中的依赖配置如下: <!-- shiro配置 --> <dependency> <gr ...

  2. mybatis实战教程(mybatis in action)之六:与Spring MVC 的集成

    前面几篇文章已经讲到了mybatis与spring 的集成.但这个时候,所有的工程还不是web工程,虽然我一直是创建的web 工程.今天将直接用mybatis与Spring mvc 的方式集成起来,源 ...

  3. spring mvc mybatis集成踩的坑

    开园这么多年了也没写几篇文章,现在想想光看别人的也不行啊,咱也自己写写,就写这天我我在做spring mvc与mybatis的集成时遇到的问题 1 spring与mybatis的集成 这个相信大家都弄 ...

  4. mybatis :与Spring MVC 的集成

    用mybatis与Spring mvc 的方式集成起来,源码在本文结尾处下载.主要有以下几个方面的配置1. web.xml 配置 spring dispatchservlet ,比如为:mvc-dis ...

  5. Mybatis学习(6)与Spring MVC 的集成

    前面几篇文章已经讲到了mybatis与spring 的集成.但这个时候,所有的工程还不是web工程,虽然我一直是创建的web 工程.今天将直接用mybatis与Spring mvc 的方式集成起来,源 ...

  6. Java Spring MVC项目搭建(一)——Spring MVC框架集成

    1.Java JDK及Tomcat安装 我这里安装的是JDK 1.8 及 Tomcat 8,安装步骤详见:http://www.cnblogs.com/eczhou/p/6285248.html 2. ...

  7. Spring MVC 中急速集成 Shiro 实践

    相信有很多的程序员,不愿意进行用户管理这块代码实现. 原因之一,不同的JavaEE 系统,用户管理都会有个性化的实现,逻辑很繁琐. 而且是系统门面,以后背锅的几率非常大,可谓是低收益高风险. 最近在系 ...

  8. Spring mvc 中有关 Shiro 1.2.3 配置问题

    Spring 版本:3.2.x,  4.0.x [问题说明] 首先介绍下配置出错情况: (1)项目中,Spring3 and Spring4 的 applicationContext.xml aop ...

  9. springboot (spring mvc)集成swagger

    最近用springboot构建rest接口,考虑到最方便的验证接口,想到了引入swagger. 基本的步骤大致如下: 1.pom中引入swagger依赖: <dependency> < ...

随机推荐

  1. NSString与奇怪的retainCount

    话题从sunnyxx的<黑幕背后的Autorelease>开始 文章开头有个小例子 __weak id reference = nil;- (void)viewDidLoad { [sup ...

  2. ORACLE与mysql中查询第n条到第m条的数据记录的方法

    ORACLE: SELECT * FROM             (                  SELECT 表名.*, ROWNUM AS CON FROM 表名 WHERE ROWNUM ...

  3. MongoDB Shard部署及Tag的使用

    Shard部署 准备测试环境 为准备数据文件夹 Cd  /home/tiansign/fanr/mongodb/Shard mkdir configdb1 configdb2 configdb3 mk ...

  4. Mongodb Manual阅读笔记:CH3 数据模型(Data Models)

    3数据模型(Data Models) Mongodb Manual阅读笔记:CH2 Mongodb CRUD 操作Mongodb Manual阅读笔记:CH3 数据模型(Data Models)Mon ...

  5. Nginx 简单的负载均衡配置示例(转载)

    原文地址:Nginx 简单的负载均衡配置示例(转载) 作者:水中游于 www.s135.com 和 blog.s135.com 域名均指向 Nginx 所在的服务器IP. 用户访问http://www ...

  6. js 求时间差

    var date1=new Date();  //开始时间 var date2=new Date();    //结束时间 var date3=date2.getTime()-date1.getTim ...

  7. 开窗函数 --over()

    一个学习性任务:每个人有不同次数的成绩,统计出每个人的最高成绩. 这个问题应该还是相对简单,其实就用聚合函数就好了. select id,name,max(score) from Student gr ...

  8. 0014 Java学习笔记-集合-HashMap集合

    主要的方法 + 构造方法: * HashMap(); - 默认大小16,负载因子0.75 * HashMap(int initialCapacity); * HashMap(int initialCa ...

  9. 006.udp转发包并代理访问服务器总结

    背景: 当加速器(client)拦截了游戏客户端发送的完整数据包(package)时,将package传给中间服务器(mid_server),经过自己的链路传输数据之后,中间服务器模拟游戏客户端将数据 ...

  10. Configure Ocserv on CentOS 6

    Configure Ocserv on CentOS 6 Table of Contents 1. Install ocserv 2. Configure ocserv 3. How to host ...