Shiro登录中遇到了问题

记录二次开发中遇到的问题, 如果系统学习Shiro, 推荐跟我学Shrio.

问题

  1. 项目是要将验证从本地改为LDAP验证, 但是因为jeecms的验证和授权中, 用户和角色以及权限的信息都来自本地, 大量的改造不适合.
  2. 域名的拦截, 因为IP被重置

HTTP 302

HTTP 302 Found 重定向状态码表明请求的资源被暂时的移动到了由Location 头部指定的 URL 上。就是请求的资源被重定向到了新的地址。

要查看Filter是否对关键词路径进行了拦截。

Shiro

项目中用的jeecms, 安全验证用的shiro,架构是Spring+SpringMVC,查看了一下web.xml,有关于shiro的filter,用的DelegatingFilterProxy类做代理,在SpringContext中配置Shiro的bean。

DelegatingFilterProxy

是对于servlet filter的代理,通过spring容器管理filter的生命周期,可以通过Spring容器注入需要的bean,以及读取需要的配置文件。

【web.xml】

<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

【shiroContext.xml】

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
</bean>

拦截器链

  1. 先执行Shiro自己的Filter链
  2. 执行Servlet的Filter链

自定义拦截器

  1. 可以根据自己的需求扩展拦截器,继承要扩展的拦截器
  2. 对相应的方法进行扩展
  3. 在配置文件中修改对应的Filter类名
// 代码参考<跟我学shiro>
public class MyAccessControlFilter extends AccessControlFilter {
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
System.out.println("access allowed");
return true;
}
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
System.out.println("访问拒绝也不自己处理,继续拦截器链的执行");
return true;
}
}
[filters]
myFilter4=com.github.zhangkaitao.shiro.chapter8.web.filter.MyAccessControlFilter
[urls]
/** 代码参考<跟我学shiro>

执行过程

  1. ShiroFilter提供Shiro的入口
  2. AdviceFilter提供AOP的风格,分为preHandler,postHandle,afterCompletion三个方法针对AOP的前后增强(预处理和进行后处理)
  3. PathMatchingFilter匹配ANT风格的请求路径,解析拦截器参数
    1. onPreHandle方法将路径绑定参数配置传给mappedValue,然后进行一些验证
  4. AccessControlFilter访问控制功能,如是否允许访问,拒绝后如何处理等
    1. isAccessAllowed表示是否允许访问
    2. onAccessDenied表示当拒绝访问时是否处理了
  5. 如果扩展访问控制可以继承AccessControlFilter,如果添加通用数据可以继承PathMatchingFilter

DelegatingSubject

shiro通过FormAuthenticationFilter来进行表单验证,如果在验证前要进行其他比如验证码的验证,可以自定义一个继承的子类.扩展对应的方法.

这里是对访问控制的扩展,继承关系为:FormAuthenticationFilter --> AuthenticatingFilter --> AuthenticationFilter --> AccessControlFilter.

可以在扩展的拦截器中重写executeLogin方法,在里面扩展对访问的控制

// 源码
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 {
Subject subject = getSubject(request, response);
subject.login(token);
return onLoginSuccess(token, subject, request, response);
} catch (AuthenticationException e) {
return onLoginFailure(token, e, request, response);
}
}

这里的执行是获取当前的subject --> 根据请求创建token -->执行subject.login()方法 --> 返回成功或者失败的处理

login()方法执行中,会进行一系列的处理,首先是交给DelegatingSubject,后面的没有详细研究,最后调用realm的doGetAuthenticationInfo方法获取身份验证的相关信息,通过SimpleAuthenticationInf返回AuthenticationInfo.

SimpleAuthenticationInfo

用来返回AuthenticationInfo信息,而AuthenticationInfo有两个作用

  1. 如果Realm是AuthenticatingRealm子类,则提供给AuthenticatingRealm内部使用的CredentialsMatcher进行凭据验证
  2. 提供给SecurityManager来创建Subject(提供身份信息)

credentialsMatcher

protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {
CredentialsMatcher cm = getCredentialsMatcher();
if (cm != null) {
if (!cm.doCredentialsMatch(token, info)) {
//not successful - throw an exception to indicate this:
String msg = "Submitted credentials for token [" + token + "] did not match the expected credentials.";
throw new IncorrectCredentialsException(msg);
}
} else {
throw new AuthenticationException("A CredentialsMatcher must be configured in order to verify " +
"credentials during authentication. If you do not wish for credentials to be examined, you " +
"can configure an " + AllowAllCredentialsMatcher.class.getName() + " instance.");
}
}

CredentialsMatcher实现了token和info的凭证验证.

授权问题

关于授权, 一开始进入了一个误区, 认为在通过验证之后会走授权的部分, 当页面出现授权问题的时候, 发现打过的断点没有进去, 仔细看了下开涛大神的讲解,  是当要访问对应的资源时, 才会验证当前用户的授权情况.

如果想对资源设置权限, 可以应用Spring的AOP注解, 在对应的AnnotationController控制器(你的Controller)上加@RequiresRoles("admin"), 如果抛出异常, 可以用Spring的ExceptionHandler拦截处理.

判断是否已通过验证

// 获取到当前subject
Subject subject = SecurityUtils.getSubject();
// 判断是否已通过验证或者已经记住
if (subject.isAuthenticated()|| subject.isRemembered()) {
...
}

问题1解决方式

不改造本地验证和授权方式, 让ldap用户落地, 但是不包括密码, 每次根据user和password去判断验证的方式和是否新增用户.

在继承了AuthorizingRealm的CmsAuthorizingRealm类中修改doGetAuthenticationInfo方法即可.

问题2解决方式

原因

因为登陆后Cookie里面设置了域名,如果当前访问的域名和这个Cookie的域名不一致,将无法登陆成功。

但是域名和IP本地做了映射,并且在系统中做了配置,应该不是因为域名和IP而导致的创建了不同的session,更何况session的唯一标示是Jsessionid。

但是cookie是根据域名匹配的,如果域名被修改,那么就会导致后台拿不到JSESSIONID,也就会显示当前未登录。

而现在系统的部署,域名是虚拟生成的,任何访问的客户端,本地域名都不会被看到,推断是因为这个原因导致。

Shiro登录中遇到了问题的更多相关文章

  1. spring boot(十四)shiro登录认证与权限管理

    这篇文章我们来学习如何使用Spring Boot集成Apache Shiro.安全应该是互联网公司的一道生命线,几乎任何的公司都会涉及到这方面的需求.在Java领域一般有Spring Security ...

  2. 使用Shiro登录成功后,跳转到之前访问的页面实现

    转:http://blog.csdn.net/lhacker/article/details/20450855 很多时候,我们需要做到,当用户登录成功后,跳转回登录前的页面.如果用户是点击" ...

  3. Shiro 登录认证源码详解

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

  4. 简单两步快速实现shiro的配置和使用,包含登录验证、角色验证、权限验证以及shiro登录注销流程(基于spring的方式,使用maven构建)

    前言: shiro因为其简单.可靠.实现方便而成为现在最常用的安全框架,那么这篇文章除了会用简洁明了的方式讲一下基于spring的shiro详细配置和登录注销功能使用之外,也会根据惯例在文章最后总结一 ...

  5. shiro登录验证简单理解

    这两天接手了下师兄的项目,要给系统加个日志管理模块,其中需要记录登录功能的日志,那么首先要知道系统的登录是在哪里实现验证的. 该系统把所有登录验证还有权限控制的工作都交给了shiro. 这篇文章就先简 ...

  6. 浅谈Shiro框架中的加密算法,以及校验

    在涉及到密码存储问题上,应该加密/生成密码摘要存储,而不是存储明文密码.为什么要加密:网络安全问题是一个很大的隐患,用户数据泄露事件层出不穷,比如12306账号泄露. Shiro提供了base64和1 ...

  7. shiro登录认证过程讲解

      先粘出登录的代码 1. 可以看到已经获取到了username和password ,为了接下来的认证过程,我们需要获取subject对象,也就是代表当前登录用户,并且要将username和passw ...

  8. 权限的分类(shiro项目中来的五)

    第一种权限:菜单栏展示还是不展示的权限(粗颗粒) 实现方法,在SYS_ROLE表中添加一个字段rights,通过 public static BigInteger sumRights(String[] ...

  9. Ubuntu再图形登录中以root的身份进入???

    Ubuntu再图形登录中以root的身份进入??? 这样做的需求,应该就是,可以再图形页面以root的身份进行图形化操作,比较方便更改配置文件. 1. 可以实现,但是不建议这么做,之后会出现一个警告提 ...

随机推荐

  1. 在MyEclipse中使用javadoc导出API文档详解

    本篇文档介绍如何在MyEclipse中导出javadoc(API)帮助文档,并且使用htmlhelp.exe和jd2chm.exe生成chm文档. 具体步骤如下: 打开MyEclipse,选中想要制作 ...

  2. 阿里云服务器Linux常用命令

    系统信息 arch 显示机器的处理器架构(1) uname -m 显示机器的处理器架构(2) uname -r 显示正在使用的内核版本 dmidecode -q 显示硬件系统部件 - (SMBIOS ...

  3. 【Linux】 Linux编程规范&Linux 编程环境搭建

    一.通过Samba映射网络驱动器 菜单栏-计算机-映射网络驱动器 English 菜单栏-Home -Easy access-Map as drive 编辑代码使用 Windows 编译 运行程序在 ...

  4. mysql的sql_mode介绍和修改

    原文链接: http://blog.csdn.net/wulantian/article/details/8905573   mysql目录下有一个配置文件my.conf. mysql数据库有一个环境 ...

  5. SVNKit学习——svn二次开发背景和闲谈(一)

    开发背景: 简述现有流程:代码的合并.提交是以任务为最小单元的.例如A和B两个同学开发不同的任务,那就是两个任务号.合并的时候可能会先合并A的代码,在合并B的代码. 需求:SVN合并程序开发——一款能 ...

  6. matlab矩阵

    矩阵的转置用',比如: a = [1,2,3]; b = a'; %b 转置成一个列向量,可以用于矩阵 linspace是Matlab中的一个指令,用于产生指定范围内的指定数量点数,相邻数据跨度相同, ...

  7. Ruby系列文章之1---开发者应该熟悉的10个工具

    1. Git Git是进入Ruby这个生态圈首先最应该学会的工具.几乎所有以Ruby开发出来的套件都放在Github上.也就是不管你要下载或修改协作都需要透过Git. 2. RVM Ruby有很多种i ...

  8. HDU 4757 Tree(可持续化字典树,lca)

    题意:询问树上结点x到结点y路上上的权值异或z的最大值. 任意结点权值 ≤ 2^16,可以想到用字典树. 但是因为是询问某条路径上的字典树,将字典树可持续化,字典树上的结点保存在这条路径上的二进制数. ...

  9. Android(java)学习笔记44:Map集合的遍历之键值对对象找键和值

    1. Map集合的遍历之 键值对对象找 键和值: package cn.itcast_01; import java.util.HashMap; import java.util.Map; impor ...

  10. Spring 的AOP底层实现技术:JDK和CGLIB动态代理

    Spring 的AOP实现技术之JDK的动态代理技术实例: 接口:IUserService (Spring的AOP是动态AOP,实现技术:JDK提供的动态代理和cglib代理,cglib它可以为没有实 ...