摘要:

本篇博文是“Java秒杀系统实战系列文章”的第五篇,在本篇博文中,我们将整合权限认证-授权框架Shiro,实现用户的登陆认证功能,主要用于:要求用户在抢购商品或者秒杀商品时,限制用户进行登陆!并对于特定的url(比如抢购请求对应的url)进行过滤(即当用户访问指定的url时,需要要求用户进行登陆)。内容:

对于Shiro,相信各位小伙伴应该听说过,甚至应该也使用过!简单而言,它是一个很好用的用户身份认证、权限授权框架,可以实现用户登录认证,权限、资源授权、会话管理等功能,在本秒杀系统中,我们将主要采用该框架实现对用户身份的认证和用户的登录功能。
值得一提的是,本篇博文介绍的“Shiro实现用户登录认证”功能模块涉及到的数据库表为用户信息表user,下面进入代码实战环节。

<!--

(2)紧接着是在UserController控制器中开发用户前往登录、用户登录以及用户退出登录的请求对应的功能方法,其完整的源代码如下所示:

@Autowired
private Environment env;//跳到登录页
@RequestMapping(value = {"/to/login","/unauth"})
public String toLogin(){return "login";
}//登录认证
@RequestMapping(value = "/login",method = RequestMethod.POST)
public String login(@RequestParam String userName, @RequestParam String password, ModelMap modelMap){String errorMsg="";try {if (!SecurityUtils.getSubject().isAuthenticated()){String newPsd=new Md5Hash(password,env.getProperty("shiro.encrypt.password.salt")).toString();UsernamePasswordToken token=new UsernamePasswordToken(userName,newPsd);SecurityUtils.getSubject().login(token);}}catch (UnknownAccountException e){errorMsg=e.getMessage();modelMap.addAttribute("userName",userName);}catch (DisabledAccountException e){errorMsg=e.getMessage();modelMap.addAttribute("userName",userName);}catch (IncorrectCredentialsException e){errorMsg=e.getMessage();modelMap.addAttribute("userName",userName);}catch (Exception e){errorMsg="用户登录异常,请联系管理员!";e.printStackTrace();}if (StringUtils.isBlank(errorMsg)){return "redirect:/index";}else{modelMap.addAttribute("errorMsg",errorMsg);return "login";}
}//退出登录
@RequestMapping(value = "/logout")
public String logout(){SecurityUtils.getSubject().logout();return "login";
}

其中,在匹配用户的密码时,我们在这里采用的Md5Hash的方法,即MD5加密的方式进行匹配(因为数据库的user表中用户的密码字段存储的正是采用MD5加密后的加密串)
前端页面login.jsp的内容比较简单,只需要用户输入最基本的用户名和密码即可,如下图所示为该页面的部分核心源代码:

当前端提交“用户登录”请求时,将以“提交表单”的形式将用户名、密码提交到后端UserController控制器对应的登录方法中,该方法首先会进行最基本的参数判断与校验,校验通过之后,会调用Shiro内置的组件SecurityUtils.getSubject().login()方法执行登录操作,其中的登录操作将主要在 “自定义的Realm的doGetAuthenticationInfo方法”中执行。
(3)接下来是基于Shiro的AuthorizingRealm,开发自定义的Realm,并实现其中的用户登录认证方法,即doGetAuthenticationInfo()方法。其完整的源代码如下所示:

/*** 用户自定义的realm-用于shiro的认证、授权* @Author:debug (SteadyJack)* @Date: 2019/7/2 17:55**/
public class CustomRealm extends AuthorizingRealm{private static final Logger log= LoggerFactory.getLogger(CustomRealm.class);private static final Long sessionKeyTimeOut=3600_000L;@Autowiredprivate UserMapper userMapper;//授权@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {return null;}//认证-登录@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken;String userName=token.getUsername();String password=String.valueOf(token.getPassword());log.info("当前登录的用户名={} 密码={} ",userName,password);User user=userMapper.selectByUserName(userName);if (user==null){throw new UnknownAccountException("用户名不存在!");}if (!Objects.equals(1,user.getIsActive().intValue())){throw new DisabledAccountException("当前用户已被禁用!");}if (!user.getPassword().equals(password)){throw new IncorrectCredentialsException("用户名密码不匹配!");}SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(user.getUserName(),password,getName());setSession("uid",user.getId());return info;}/*** 将key与对应的value塞入shiro的session中-最终交给HttpSession进行管理(如果是分布式session配置,那么就是交给redis管理)* @param key* @param value*/private void setSession(String key,Object value){Session session=SecurityUtils.getSubject().getSession();if (session!=null){session.setAttribute(key,value);session.setTimeout(sessionKeyTimeOut);}}
}

其中,userMapper.selectByUserName(userName);主要用于根据userName查询用户实体信息,其对应的动态Sql的写法如下所示:

<!--根据用户名查询-->
<select id="selectByUserName" resultType="com.debug.kill.model.entity.User">SELECT <include refid="Base_Column_List"/>FROM userWHERE user_name = #{userName}
</select>

值得一提的是,当用户登录成功时(即用户名和密码的取值跟数据库的user表相匹配),我们会借助Shiro的Session会话机制将当前用户的信息存储至服务器会话中,并缓存一定时间!(在这里是3600s,即1个小时)!

(4)最后是我们需要实现“用户在访问待秒杀商品详情或者抢购商品或者任何需要进行拦截的业务请求时,如何自动检测用户是否处于登录的状态?如果已经登录,则直接进入业务请求对应的方法逻辑,否则,需要前往用户登录页要求用户进行登录”。

基于这样的需求,我们需要借助Shiro的组件ShiroFilterFactoryBean 实现“用户是否登录”的判断,以及借助FilterChainDefinitionMap拦截一些需要授权的链接URL,其完整的源代码如下所示:

/*** shiro的通用化配置* @Author:debug (SteadyJack)* @Date: 2019/7/2 17:54**/
@Configuration
public class ShiroConfig {@Beanpublic CustomRealm customRealm(){return new CustomRealm();}@Beanpublic SecurityManager securityManager(){DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();securityManager.setRealm(customRealm());securityManager.setRememberMeManager(null);return securityManager;}@Beanpublic ShiroFilterFactoryBean shiroFilterFactoryBean(){ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean();bean.setSecurityManager(securityManager());bean.setLoginUrl("/to/login");bean.setUnauthorizedUrl("/unauth");//对于一些授权的链接URL进行拦截Map<String, String> filterChainDefinitionMap=new HashMap<>();filterChainDefinitionMap.put("/to/login","anon");filterChainDefinitionMap.put("/**","anon");filterChainDefinitionMap.put("/kill/execute","authc");filterChainDefinitionMap.put("/item/detail/*","authc");bean.setFilterChainDefinitionMap(filterChainDefinitionMap);return bean;}}

从上述该源代码中可以看出,Shiro的ShiroFilterFactoryBean组件将会对 URL=/kill/execute 和 URL=/item/detail/* 的链接进行拦截,即当用户访问这些URL时,系统会要求当前的用户进行登录(前提是用户还没登录的情况下!如果已经登录,则直接略过,进入实际的业务模块!)
除此之外,Shiro的ShiroFilterFactoryBean组件还设定了 “前往登录页”和“用户没授权/没登录的前提下的调整页”的链接,分别是 /to/login 和 /unauth!
(5)至此,整合Shiro框架实现用户的登录认证的前后端代码实战已经完毕了,将项目/系统运行在外置的tomcat服务器中,打开浏览器即可访问进入“待秒杀商品的列表页”,点击“详情”,此时,由于用户还没登陆,故而将跳转至用户登录页,如下图所示:

输入用户名:debug,密码:123456,点击“登录”按钮,即可登录成功,并成功进入“详情页”,如下图所示:

登录成功之后,再回到刚刚上一个列表页,即“待秒杀商品的列表页”,再次点击“详情”按钮,此时会直接进入“待秒杀商品的详情页”,而不会跳转至“用户登录页”,而且用户的登录态将会持续1个小时!(这是借助Shiro的Session的来实现的)。

补充:
由于相应的博客的更新可能并不会很快,故而如果有想要快速入门以及实战整套系统的,可以阅读: Java商城秒杀系统的设计与实战视频教程(SpringBoot版) https://www.roncoo.com/view/1146338929757712386

java 权限url权限_Java秒杀系统实战系列~整合Shiro实现用户登录认证相关推荐

  1. java设计前期工作基础和存在的困难_Java秒杀系统实战系列-基于Redisson的分布式锁优化秒杀逻辑...

    本文是"Java秒杀系统实战系列文章"的第十五篇,本文我们将借助综合中间件Redisson优化"秒杀系统中秒杀的核心业务逻辑",解决Redis的原子操作在优化秒 ...

  2. java 模块 分工_Java秒杀系统实战系列~构建SpringBoot多模块项目

    摘要:本篇博文是"Java秒杀系统实战系列文章"的第二篇,主要分享介绍如何采用IDEA,基于SpringBoot+SpringMVC+Mybatis+分布式中间件构建一个多模块的项 ...

  3. java 唯一编号_Java秒杀系统实战系列~分布式唯一ID生成订单编号

    摘要: 本篇博文是"Java秒杀系统实战系列文章"的第七篇,在本博文中我们将重点介绍 "在高并发,如秒杀的业务场景下如何生成全局唯一.趋势递增的订单编号",我们 ...

  4. java 秒杀代码_Java秒杀系统实战系列~商品秒杀代码实战

    摘要: 本篇博文是"Java秒杀系统实战系列文章"的第六篇,本篇博文我们将进入整个秒杀系统核心功能模块的代码开发,即"商品秒杀"功能模块的代码实战. 内容: & ...

  5. asp按时间自动递增编号_Java秒杀系统实战系列-分布式唯一ID生成订单编号

    本文是"Java秒杀系统实战系列文章"的第七篇,在本文中我们将重点介绍 "在高并发,如秒杀的业务场景下如何生成全局唯一.趋势递增的订单编号",我们将介绍两种方法 ...

  6. ieee39节点系统介绍_Java秒杀系统实战系列-基于ZooKeeper的分布式锁优化秒杀逻辑...

    本文是"Java秒杀系统实战系列文章"的第十六篇,本文我们将继续秒杀系统的优化之路,采用统一协调调度中心中间件ZooKeeper控制秒杀系统中高并发多线程对于共享资源~代码块的并发 ...

  7. sql取系统时间减一小时_Java秒杀系统实战系列-整体业务流程介绍与数据库设计...

    本篇文章是"Java秒杀系统实战系列文章"的第三篇,本文将主要介绍秒杀系统的整体业务流程,并根据相应的业务流程进行数据库设计,最终采用Mybatis逆向工程生成相应的实体类Enti ...

  8. sql判断时间大于0点_Java秒杀系统实战系列-数据库级别Sql的优化与代码的调整

    本文是"Java秒杀系统实战系列文章"的第十三篇,从本篇文章开始我们将进入"秒杀代码优化"环节,本文将首先从数据库级别Sql的优化入手,结合调整秒杀相关的部分核 ...

  9. Java秒杀系统实战系列~RabbitMQ死信队列处理超时未支付的订单(转)

    转自: https://juejin.cn/post/6844903903130042376 文末有源代码,非常棒 摘要: 本篇博文是"Java秒杀系统实战系列文章"的第十篇,本篇 ...

  10. Java秒杀系统实战系列~分布式唯一ID生成订单编号

    摘要: 本篇博文是"Java秒杀系统实战系列文章"的第七篇,在本博文中我们将重点介绍 "在高并发,如秒杀的业务场景下如何生成全局唯一.趋势递增的订单编号",我们 ...

最新文章

  1. 河南城建学院计算机分数,河南城建学院录取分数线2021是多少分(附历年录取分数线)...
  2. 关系抽取论文整理,核方法、远程监督的重点都在这里
  3. NEFU84——五指山(Exgcd)
  4. 算法题复习(快排、链表、二分、哈希、双指针)
  5. mysql怎么显示结果窗口_mysql8中窗口函数
  6. JEECG开源团队招募成员计划
  7. 一步一步学Entity FrameWork 4(1)
  8. java多线程编程_Java多线程编程
  9. 支付宝五福开奖!几个亿的项目你分到几块?
  10. 混合云存储阵列 > 产品简介 > 应用场景 > 双活容灾
  11. Spring学习总结(23)——Spring Framework 5.0 新特性
  12. Linux下的Notepad++编辑器——Notepadqq
  13. bzoj 1650: [Usaco2006 Dec]River Hopscotch 跳石子(二分)
  14. linux配置https站点
  15. 判断中文文本是否为utf8编码类型的javascript实现_Go语言实现LeetCode算法:393 UTF-8编码校验...
  16. 沃德天,Python竟然还能做实时翻译
  17. 计算机有什么简便快捷方法,运行快捷键(电脑常用快捷键大全)
  18. win10系统无法开启远程服务器配置,win10系统无法连接远程服务器的方案介绍...
  19. 2013网易实习生招聘 岗位:数据挖掘工程师
  20. 基于FPGA的数字频率计(设计全过程)

热门文章

  1. C语言联合体(union)的使用方法及其本质-union
  2. Android7.0 MTK方案 静默安装和卸载
  3. 课后作业1:字串加密
  4. Hibernate中createCriteria即QBC查询的详细用法
  5. 做项目时自己的心得体会
  6. C++动态连接库动态加载
  7. 本博文记录需要解决的问题
  8. 【转】用Terracotta实现Master-Worker
  9. Linux 内核/sys 文件系统之sysfs 属性文件
  10. 第四章 蒙特卡洛方法-强化学习理论学习与代码实现(强化学习导论第二版)