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. 2017年10月29日 数据库查询总结&45道题

    日期函数: 当前时间:GetDate() 两个时间差:DateDiff() 一. 设有一数据库,包括四个表:学生表(Student).课程表(Course).成绩表(Score)以及教师信息表(Tea ...

  2. python 爬虫初试

    python3.5  抓网易新闻的排行榜上的新闻,主要用自带的request模块和lxml import re from urllib import request from lxml import ...

  3. Java中Date()类 日期转字符串、字符串转日期的问题(已解决)

    Java中Date()类 日期转字符串.字符串转日期的问题 今天在写东西的时候突然发现一个问题,就是先new 一个Date()然后将生成的值转为字符串, 然后再将转换后的字符串再次用new Date( ...

  4. Django组件——forms组件

    一.校验字段功能 通过注册用户这个实例来学习校验字段功能. 1.模型:models.py from django.db import models # Create your models here. ...

  5. Java开发坏境配置

    在"系统变量"中设置3项属性,JAVA_HOME,PATH,CLASSPATH(大小写无所谓),若已存在则点击"编辑",不存在则点击"新建" ...

  6. Android 笔记之 Android 系统架构

    Android笔记之Android系统架构 h2{ color: #4abcde; } a{ color: blue; text-decoration: none; } a:hover{ color: ...

  7. AngularJs整合ui-bootstrap以及ui-grid

    1. ui-bootstrap 参考博客:  http://www.cnblogs.com/pilixiami/p/5597634.html  (这篇博客写的非常不错,值得推荐) angular-ui ...

  8. sql server 某列去重

    例如:某个表中,插入了两条除id外其他字段都一样的数据,但是查询的时候只想查到一条. select * from 表名 where 主键 in ( select max(主键) from 表名 gro ...

  9. 为我们的SSR程序添加热更新功能

    前沿 通过上一篇文章 通过vue-cli3构建一个SSR应用程序 我们知道了什么是SSR,以及如何通过vue-cli3构建一个SSR应用程序.但是最后遗留了一些问题没有处理,就是没有添加开发时的热更新 ...

  10. C++ double 小数精度控制

    第一种方法:cout<<fixed<<setprecision(20)<<mydouble<<endl; #include <iostream&g ...