一般的登录流程会有:用户名不存在,密码错误,验证码错误等..

  在集成shiro后,应用程序的外部访问权限以及访问控制交给了shiro来管理。

  shiro提供了两个主要功能:认证(Authentication)和授权(Authorization);认证的作用是证明自身可以访问,一般是用户名加密码,授权的作用是谁可以访问哪些资源,通过开发者自己的用户角色权限系统来控制。

  shiro的会话管理和缓存管理不在本文范围内。

  下面通过登录失败的处理流程来介绍springmvc与shiro的集成。

  项目依赖:

依赖名称  版本
spring 4.1.4.RELEASE
shiro 1.2.2
self4j 1.7.5
log4j 1.2.17

在web.xml里配置shiro

    <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>

新建一个spring-context-shiro.xml配置shiro相关信息,使用spring加载

<?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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"default-lazy-init="true"><description>Shiro Configuration</description><!-- 安全认证过滤器 --><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><property name="securityManager" ref="securityManager" /><property name="loginUrl" value="/sys/login" /><property name="successUrl" value="/sys" /><property name="filters"><map>          <!--自定义登录验证过滤器--><entry key="authc" value-ref="formAuthenticationFilter" /></map></property><property name="filterChainDefinitions"><value>/sys/login = authc/sys/logout = logout/sys/** = user</value></property></bean><!-- 定义 Shiro 主要业务对象 --><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><property name="realm" ref="systemAuthorizingRealm" /><property name="cacheManager" ref="shiroCacheManager" /></bean><!-- 会话ID生成器 --><bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/><!-- 会话管理器,设定会话超时及保存 --><bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"><!-- 全局会话超时时间(单位毫秒),默认30分钟 --><property name="globalSessionTimeout" value="1800000" /><property name="sessionDAO" ref="sessionDAO"/></bean><!-- 会话验证调度器,每30分钟执行一次验证 --><!-- <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler"> --><bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler"><property name="interval" value="1800000"/><property name="sessionManager" ref="sessionManager"/></bean><!-- sessionDAO保存认证信息 --><bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO"><property name="activeSessionsCacheName" value="shiro-activeSessionCache" /><property name="cacheManager" ref="shiroCacheManager" /><property name="sessionIdGenerator" ref="sessionIdGenerator"/></bean><!-- 用户授权信息Cache, 采用EhCache --><bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"><property name="cacheManager" ref="cacheManager" /></bean><!-- Shiro生命周期处理器 --><bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /><!-- AOP式方法级权限检查 --><bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"><property name="proxyTargetClass" value="true" /></bean><bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"><property name="securityManager" ref="securityManager" /></bean>
</beans>

新建一个登录认证过滤器FormAuthenticationFilter.java

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.stereotype.Service;/*** 表单验证(包含验证码)过滤类*/
@Service
public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.FormAuthenticationFilter {public static final String DEFAULT_CAPTCHA_PARAM = "validateCode";private String captchaParam = DEFAULT_CAPTCHA_PARAM;public String getCaptchaParam() {return captchaParam;}protected String getCaptcha(ServletRequest request) {return WebUtils.getCleanParam(request, getCaptchaParam());}protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {String username = getUsername(request);String password = getPassword(request);String locale = request.getParameter("locale");if (password == null) {password = "";}boolean rememberMe = isRememberMe(request);String host = getHost(request);String captcha = getCaptcha(request);return new UsernamePasswordToken(username, password.toCharArray(),locale, rememberMe, host, captcha);}
}

新建令牌类UsernamePasswordToken.java

package com.chunhui.webservice.modules.sys.security;/*** 用户和密码(包含验证码)令牌类*/
public class UsernamePasswordToken extends org.apache.shiro.authc.UsernamePasswordToken {private static final long serialVersionUID = 1L;private String captcha;private String locale;public String getCaptcha() {return captcha;}public void setCaptcha(String captcha) {this.captcha = captcha;}public String getLocale() {return locale;}public void setLocale(String locale) {this.locale = locale;}public UsernamePasswordToken() {super();}public UsernamePasswordToken(String username, char[] password, boolean rememberMe, String host, String captcha) {super(username, password, rememberMe, host);this.captcha = captcha;}public UsernamePasswordToken(String username, char[] password, String locale,boolean rememberMe, String host, String captcha) {super(username, password, rememberMe, host);this.captcha = captcha;this.locale = locale;}
}

最后一个是认证实现类SystemAuthorizationRealm:

package com.chunhui.webservice.modules.sys.security;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;import com.chunhui.webservice.common.utils.EmployeeType;
import com.chunhui.webservice.common.utils.VertifyStatus;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;
import com.chunhui.webservice.common.servlet.ValidateCodeServlet;
import com.chunhui.webservice.common.utils.SpringContextHolder;
import com.chunhui.webservice.modules.sys.entity.Employee;
import com.chunhui.webservice.modules.sys.entity.Menu;
import com.chunhui.webservice.modules.sys.service.SystemService;
import com.chunhui.webservice.modules.sys.utils.SystemUtils;
import com.chunhui.webservice.modules.sys.web.LoginController;/*** 系统安全认证实现类*/
@Service
@DependsOn({ "employeeDao", "roleDao", "menuDao" })
public class SystemAuthorizingRealm extends AuthorizingRealm {private SystemService systemService;/*** 认证回调函数, 登录时调用*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
// 判断验证码Session session = SecurityUtils.getSubject().getSession();// 设置独立的session会话超时时间  session.setTimeout(60000);String code = (String) session.getAttribute(ValidateCodeServlet.VALIDATE_CODE);if (token.getCaptcha() == null || !token.getCaptcha().toUpperCase().equals(code)) {throw new CaptchaException("验证码错误!");}         //如果帐号不存在,输出//throw new UnknownAccountException();//如果帐号被禁用,输出            //throw new DisabledAccountException();//保存登录时选择的语言SecurityUtils.getSubject().getSession().setAttribute("locale", token.getLocale());try{SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(new Principal(employee), employee.getPassword(), getName());return info;}catch (Throwable t){t.printStackTrace();throw new AuthenticationException();}}/*** 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {Principal principal = (Principal) getAvailablePrincipal(principals);Employee employee = getSystemService().getEmployeeByName(principal.getUsername());if (employee != null) {SystemUtils.putCache("employee", employee);SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();List<Menu> list = SystemUtils.getMenuList();for (Menu menu : list) {if (StringUtils.isNotBlank(menu.getPermission())) {// 添加基于Permission的权限信息for (String permission : StringUtils.split(menu.getPermission(), ",")) {info.addStringPermission(permission);}}}// 更新登录IP和时间
            getSystemService().updateEmployeeLoginInfo(employee.getId());return info;} else {return null;}}/*** 清空用户关联权限认证,待下次使用时重新加载*/public void clearCachedAuthorizationInfo(String principal) {SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());clearCachedAuthorizationInfo(principals);}/*** 清空所有关联认证*/public void clearAllCachedAuthorizationInfo() {Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();if (cache != null) {for (Object key : cache.keys()) {cache.remove(key);}}}/*** 获取系统业务对象*/public SystemService getSystemService() {if (systemService == null) {systemService = SpringContextHolder.getBean(SystemService.class);}return systemService;}/*** 授权用户信息*/public static class Principal implements Serializable {private static final long serialVersionUID = 1L;private String id;private String username;private String realname;private Map<String, Object> cacheMap;public Principal(Employee employee) {this.id = employee.getId();this.username = employee.getUsername();this.realname = employee.getRealname();}public String getId() {return id;}public String getUsername() {return username;}public String getRealname() {return realname;}public Map<String, Object> getCacheMap() {if (cacheMap == null) {cacheMap = new HashMap<String, Object>();}return cacheMap;}}
}

那么在JSP页面,可以通过获取登录异常具体的异常类型来在页面显示错误原因

        <%String error = (String) request.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);%><c:set var="exp_type" value="<%=error %>"/><c:set var="tips" value=""></c:set><c:if test="${fn:contains(exp_type,'CaptchaException')}"><c:set var="tips" value="验证码错误"></c:set></c:if><c:if test="${fn:contains(exp_type,'FailVertifyException')}"><c:set var="tips" value="该账号审核未通过,不允许登陆!"></c:set></c:if><c:if test="${fn:contains(exp_type,'NotVertifyException')}"><c:set var="tips" value="该账号正在审核中... 不允许登陆!"></c:set></c:if><c:if test="${fn:contains(exp_type,'UnknownAccountException')}"><c:set var="tips" value="账号不存在!"></c:set></c:if><c:if test="${fn:contains(exp_type,'DisabledAccountException')}"><c:set var="tips" value="账号不允许登陆!"></c:set></c:if><c:if test="${fn:contains(exp_type,'IncorrectCredentialsException')}"><c:set var="tips" value="密码错误!"></c:set></c:if>

 

转载于:https://www.cnblogs.com/nosqlcoco/p/5579081.html

springmvc集成shiro登录失败处理相关推荐

  1. SpringMvc 集成 shiro 实现权限角色管理-maven

    2019独角兽企业重金招聘Python工程师标准>>> SpringMvc 集成 shiro 实现权限角色管理 1.项目清单展示 2.项目源码解析  1)spring-context ...

  2. springmvc集成shiro后,session、request姓汪还是姓蒋 ?

    1. 疑问 我们在项目中使用了spring mvc作为MVC框架,shiro作为权限控制框架,在使用过程中慢慢地产生了下面几个疑惑,本篇文章将会带着疑问慢慢地解析shiro源码,从而解开心里面的那点小 ...

  3. springmvc集成shiro后,session、request姓汪还是姓蒋?

    1. 疑问 我们在项目中使用了spring mvc作为MVC框架,shiro作为权限控制框架,在使用过程中慢慢地产生了下面几个疑惑,本篇文章将会带着疑问慢慢地解析shiro源码,从而解开心里面的那点小 ...

  4. Shiro 登录认证源码详解

    Apache Shiro 是一个强大且灵活的 Java 开源安全框架,拥有登录认证.授权管理.企业级会话管理和加密等功能,相比 Spring Security 来说要更加的简单. 本文主要介绍 Shi ...

  5. springMVC结合Shiro实现登录失败次数过多锁定账户功能

    本文主要记录了自己遇到了一些坑,以及需要注意的细节 主要部分源码点我 提取码:jwvx 前言 添加依赖等等其他人的教程里都有,就不浪费时间解释了: application-shiro.xml 配置文件 ...

  6. springmvc+mybatis+shiro MD5加密匹配登录失败超次数锁定帐号

    shiro的身份认证的流程,大致是这样的:当我们调用subject.login(token)的时候,首先这次身份认证会委托给Security Manager,而Security Manager又会委托 ...

  7. apache shiro jar包_只需要6个步骤,springboot集成shiro,并完成登录

    小Hub领读: 导入jar包,配置yml参数,编写ShiroConfig定义DefaultWebSecurityManager,重写Realm,编写controller,编写页面,一气呵成.搞定,是个 ...

  8. shiro登陆失败提示_shiro在springMVC 如何处理登陆失败跳到登陆页面呢?

    我的登陆的方法: @RequestMapping(value = "/dologin.req") public String doLogin(HttpServletRequest ...

  9. 集成代码生成器 SpringMVC mybatis shiro druid bootstrap HTML5

    获取[下载地址]   QQ: 313596790 官网 http://www.fhadmin.org/ A 调用摄像头拍照,自定义裁剪编辑头像,头像图片色度调节 B 集成代码生成器 [正反双向](单表 ...

  10. springmvc+spring+mybatis+maven项目集成shiro进行用户权限控制【转】

    项目结构: 1.maven项目的pom中引入shiro所需的jar包依赖关系 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ...

最新文章

  1. 一篇文章搞懂Filebeat
  2. java如何映射mysql枚举_java中自定义枚举enum映射到mysql数据库字段处理器handler
  3. python 重复输出字符串
  4. 170 道 Python 爬虫面试题(2019 版)
  5. 计算机网络——数据帧和数据包的区别
  6. 操作集合的工具类Collections
  7. 谷歌开源代码评审规范:好坏代码应该这样来判断
  8. 从计算机系统结构的发展和演变看,近代计算机是以,西南民族大学计算机系统结构试卷B有答案.doc...
  9. usb, micro-usb card 损坏, 数据恢复
  10. 前端程序员专用的在线工具箱
  11. input/output is not in graph tf.layers.conv2d在name命名时会自动在其后添加Conv2D
  12. Unity鼠标事件详解
  13. 《动手学深度学习》(PyTorch版)代码注释 - 54 【Text_sentiment_classification(RNN)】
  14. 猎头猎取人才会注重人才的哪些点?
  15. 2017秋招、春招、实习生招聘区别
  16. Python做接口测试生成测试报告失败
  17. 《游戏引擎架构》读书笔记(二)
  18. 简历c语言项目,C/C++:如何介绍简历中的项目?
  19. 如何实现类似锚链接的导航联动效果
  20. 红黑树的节点颜色是什么决定_为什么选择颜色可能是您最重要的品牌决定

热门文章

  1. PAT (Basic Level) Practice1026 程序运行时间
  2. 再论数据仓库与数据库的区别
  3. http协议报文格式原理图
  4. 判断当前用户与审批人是否属于同一个部门
  5. 数据流(任务并行库 TPL)
  6. Hibernate配置文件
  7. Debian中proftpd+mysql+虚拟用户+匿名用户+磁盘限额的配置
  8. 深入浅出ObjC之消息
  9. 函数-函数进阶-装饰器
  10. yum命令报错 yum update File /usr/bin/yum, line 30 except KeyboardInterrupt, e: --CentOS7.5