公司自用的管理系统使用了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. VS引用文件出现黄色感叹号丢失文件,应该如何解决?

    VS是微软开发的一款超级强大的IDE,深受广大.net开发者喜爱. 但是再强大,也会有它的bug和缺点. 多人协同开发时,不知道你有没有遇到一个这样的情况:第二天上班,早早来到公司,打开电脑,拉取一下 ...

  2. ​综述 | SLAM回环检测方法

    本文作者任旭倩,公众号:计算机视觉life成员,由于格式原因,公式显示可能出问题,建议阅读原文链接:综述 | SLAM回环检测方法 在视觉SLAM问题中,位姿的估计往往是一个递推的过程,即由上一帧位姿 ...

  3. 随笔编号-07 JS针对时间操作

    //获取完整的当前日期 var date=new Date; var year=date.getFullYear(); var month=date.getMonth()+1; month =(mon ...

  4. Python源码学习Schedule

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  5. Commons组件实现文件上传与下载

    一.文件上传 所需jar包 首先是commons-fileupload.jar包 其次是commons-IO.jar包 前者的使用依赖后者,两者缺一不可 实现 前台要求 在前台提交的form表单请求方 ...

  6. CentOS7下使用SonatypeNexus3搭建Docker私有仓库

    前置条件:安装docker(如果机器上没有安装的话) //安装一些必要的系统工具: sudo yum install -y yum-utils device-mapper-persistent-dat ...

  7. odoo12从零开始:二、个性化定制odoo12 之 创建数据库页面

    剧情回顾 上一文章,我们已经成功运行了odoo12,并访问localhost:8069看到如下界面: 我们还没有创建数据库,但是我们发现,数据库管理页面的logo是odoo,数据库页面全是英文的,对于 ...

  8. JMeter特点&性能测试工具选型的原则&模拟压力的原理

    1.JMeter自身的特点 1)开源.轻量级.更适合自动化和持续集成(100M左右,LoadRunner 4G左右) 2)学习难度大 3)资料少.全英文 2. 性能测试工具选型的原则 1)成本 a.工 ...

  9. hihocoder #1608 : Jerry的奶酪(状压dp)

    题目链接:http://hihocoder.com/problemset/problem/1608 题解:就是一道简单的状压dp由于dfs过程中只需要几个点之间的转移所以只要预处理一下几个点就行. # ...

  10. 2018中国大学生程序设计竞赛 - 网络选拔赛 hdu 6440 Dream 模拟

    Dream Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Subm ...