公司自用的管理系统使用了shiro,但是对于这个登录页面跳转、登录的过程逻辑以及登录成功或者失败的跳转页面一直不理解,查看相关文档资料,整理出一些结果并本地调试测试,记录下备以后回顾之用。

对于spring+shiro,很多文档都是:搭建环境,然后配置web.xml,shiro spring配置文件,开发自己的realm、shiro的过滤器链以及spring controller等等内容。实际开发中,也是按照这套路来使用的。但是:对于localhost/xxx/login登录请求页面跳转,怎么感觉是直接请求spring而未通过shiro过滤器?

本地web.xml配置文件部分截图:

shiro配置:

spring mvc作为请求控制器,shiro作为权限过滤器,shiro对所有请求url进行判断,并指定相关的过滤器,例如/xxx/login指定的是authc过滤器(验证,这些页面必须验证后才能访问,也就是我们说的登录后才能访问),过滤器逻辑如果抛出异常表示认证失败,过滤器会转向shiroFilter配置的loginUrl地址,认证成功会转向配置的successUrl地址。而转向过后的逻辑将是由springmvc来控制。

登录时验证:

 /**
*
*/
package com.autrade.xxx.shiro; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse; import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.stereotype.Service; import com.autrade.sptmasterweb.util.FailCacheUtils; /**
* 表单验证(包含验证码)过滤类 *
*/
@Service
public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.FormAuthenticationFilter { public static final String DEFAULT_MESSAGE_PARAM = "message"; @Override
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
AuthenticationToken token = createToken(request, response);
if (token == null) {
String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken " +
"must be created in order to execute a login attempt.";
throw new IllegalStateException(msg);
}
try {
Long lockTime = FailCacheUtils.isLocked(token.getPrincipal().toString());
if (lockTime>0){
request.setAttribute(DEFAULT_MESSAGE_PARAM, "错误次数过多,请稍后再试!");
return true;
}
Subject subject = getSubject(request, response); //代表当前前台传过来的用户
subject.login(token);
return onLoginSuccess(token, subject, request, response);
} catch (AuthenticationException e) {
return onLoginFailure(token, e, request, response);
}
}
/**
* 登录失败调用事件
*/
@Override
protected boolean onLoginFailure(AuthenticationToken token,
AuthenticationException e, ServletRequest request, ServletResponse response) {
String className = e.getClass().getName(), message = "";
if (IncorrectCredentialsException.class.getName().equals(className)
|| UnknownAccountException.class.getName().equals(className)){
message = "用户或密码错误, 请重试.";
}
else if (e.getMessage() != null && StringUtils.indexOf(e.getMessage(), "msg:")!=-1){
message = StringUtils.replace(e.getMessage(), "msg:", "");
}
else{
message = "系统出现点问题,请稍后再试!";
e.printStackTrace(); // 输出到控制台
}
request.setAttribute(getFailureKeyAttribute(), className);
request.setAttribute(DEFAULT_MESSAGE_PARAM, message);
String username = WebUtils.getCleanParam(request, FormAuthenticationFilter.DEFAULT_USERNAME_PARAM);
FailCacheUtils.addFailCnt(username);
return true;
} @Override
protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,
ServletResponse response) throws Exception {
String username = WebUtils.getCleanParam(request, FormAuthenticationFilter.DEFAULT_USERNAME_PARAM);
FailCacheUtils.remave(username);
return super.onLoginSuccess(token, subject, request, response);
} }

自定义realm中:

认证:

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
     //token令牌,也就相当于一张表格,你要去验证,你就得填个表,里面写好用户名密码,交给公安局的同志给你验证
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
InternalUserDownEntity userAcctInfoEntity = internalUserService.findInternalUserInfoByUserName(token.getUsername());if (userAcctInfoEntity!=null)
{
       //用户我们可以前面的令牌也就是我说的表格来取的,我们前台提交给公安同志一个表格,里面有用户密码,
       //但需要注意的是,我们在这里并不把表格中的用户密码路数据库中的用户密码进行比较,我们只是根据表格中的用户名把密码查出来,
       //然后把数据库的用户密码放在一个SimpleAuthenticationInfo对象中返回即可,这位公安同志不负责验证,只负责验证的材料
InternalUserAuthEntity userAuthEntity = new InternalUserAuthEntity();
userAuthEntity.setUserId(userAcctInfoEntity.getUserId());
ShiroUser shiroUser = new ShiroUser(userAcctInfoEntity.getUserId(), token.getUsername(),token.getUsername(), userAuthEntity);
return new SimpleAuthenticationInfo(shiroUser,userAcctInfoEntity.getPassWord(), getName());
}
else
{
return null;
}
}

以上准备好比对数据,什么时候验证呢?

(1)executeLogin中调用subject.isAuthenticated()时

(2)由于之前的shiro spring配置文件中配置了/login = authc, 配了authc过滤器,shiro会自动调用subject.isAuthenticated()方法完成验证对比。

shiro+spring的更多相关文章

  1. Shiro —— Spring 环境下的使用

    一.使用 1.搭建基础环境 (1)导入 Spring 和 Shiro 的 Jar 包 正常导入 spring jar包 导入日志包 log4j-1.2.15.jar slf4j-api-1.6.1.j ...

  2. shiro+spring相关配置

    首先pom中添加所需jar包: <!-- shiro start --> <dependency> <groupId>org.apache.shiro</gr ...

  3. 【shiro】报错:Caused by: java.lang.ClassNotFoundException: org.apache.shiro.spring.LifecycleBeanPostProcessor

    Caused by: java.lang.ClassNotFoundException: org.apache.shiro.spring.LifecycleBeanPostProcessor at o ...

  4. Shiro+Spring+SpringMVC+Mybatis整合

    Demo源码地址,v1.0分支 https://github.com/jxjy/hr

  5. Spring Boot 添加Shiro支持

    前言: Shiro是一个权限.会话管理的开源Java安全框架:Spring Boot集成Shiro后可以方便的使用Session: 工程概述: (工程结构图) 一.建立Spring Boot工程 参照 ...

  6. 基于Spring + Spring MVC + Mybatis + shiro 高性能web构建

    一直想写这篇文章,前段时间 痴迷于JavaScript.NodeJs.AngularJS,做了大量的研究,对前后端交互有了更深层次的认识. 今天抽个时间写这篇文章,我有预感,这将是一篇很详细的文章,详 ...

  7. Spring MVC 急速集成 Shiro 实录

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

  8. spring 集成shiro 之 自定义过滤器

    在web.xml中加入 <!-- 过期时间配置 --> <session-config><session-timeout>3</session-timeout ...

  9. 基于Spring框架的Shiro配置

    一.在web.xml中添加shiro过滤器  <!-- Shiro filter--> <filter> <filter-name>shiroFilter</ ...

随机推荐

  1. react-navigation

    安卓端React Navigation的TabNavigator选项卡与react-native-scrollable-tab-view.FlatList一起使用,只显示第一页的内容. 解决方案: 给 ...

  2. 打包Electron项目

    先确保该项目正常运行npm run dev,结束程序, 上篇的项目运行已经提到了打包输出工具electron-packager 可以使用全局安装的方式: npm install -g electron ...

  3. React 现代化测试

    测试的动机 测试用例的书写是一个风险驱动的行为, 每当收到 Bug 报告时, 先写一个单元测试来暴露这个 Bug, 在日后的代码提交中, 若该测试用例是通过的, 开发者就能更为自信地确保程序不会再次出 ...

  4. 记一次找回win7密码

    虚拟机密码忘了.   修改启动顺序为CD,设置虚拟机光盘镜像为kali ISO(这里用的是kali 2017.2). 开启按f2进入kali live 模式 fdisk -l 查看磁盘分区,找到win ...

  5. TokuDB · 引擎特性 · HybridDB for MySQL高压缩引擎TokuDB 揭秘

    原文出处:阿里云RDS-数据库内核组 HybridDB for MySQL(原名petadata)是面向在线事务(OLTP)和在线分析(OLAP)混合场景的关系型数据库.HybridDB采用一份数据存 ...

  6. tomcat8 编写字符编码Filter过滤器无效问题

    做一个解决全站的字符编码过滤器,过滤器类和配置如下: 过滤器类: package com.charles.web.filter; import java.io.IOException; import ...

  7. Leetcode之二分法专题-154. 寻找旋转排序数组中的最小值 II(Find Minimum in Rotated Sorted Array II)

    Leetcode之二分法专题-154. 寻找旋转排序数组中的最小值 II(Find Minimum in Rotated Sorted Array II) 假设按照升序排序的数组在预先未知的某个点上进 ...

  8. Nacos整合Spring Cloud Gateway组件

    一.什么是Spring Cloud Gateway Spring Cloud Gateway是Spring Cloud官方推出的网关框架,网关作为流量入口有着非常大的作用,常见的功能有路由转发.权限校 ...

  9. TypeError: _obtain_input_shape() got an unexpected keyword argument 'include_top'

    报错 Traceback (most recent call last): File "D:/PyCharm 5.0.3/WorkSpace/3.Keras/2.Application中五款 ...

  10. springboot之swagger快速启动

    springboot之swagger快速启动 简介 介绍 可能大家都有用过swagger,可以通过ui页面显示接口信息,快速和前端进行联调. 没有接触的小伙伴可以参考官网文章进行了解下demo页面. ...