项目中需要所有首次登录的用户必须修改密码才可使用系统,项目采用的是Shiro框架。

突然想到了配置文件org.apache.shiro.spring.web.ShiroFilterFactoryBean中的loginUrl,校验未登录则跳转到登录地址。索性研究了它的源码后可以继承AccessControlFilter自定义自己的过滤器。

自定义Shiro过滤器:

package com.lwj.modules.filter;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse; import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils; import com.lwj.modules.shiro.realm.Principal; /**
* 首次登陆必须修改密码
*
* @ClassName: ChangePasswordFilter
* @author lwj
* @version 1.0.0
*/
public class ChangePasswordFilter extends AccessControlFilter { /**
* 登录地址
*/
static final String LOGIN_URL = "/login.html";
/**
* 修改密码地址
*/
static final String NEW_PASSWORD_URL = "/login/new_password.html"; @Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception {
// TODO Auto-generated method stub
return false;
} @Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { Subject subject = getSubject(request, response);
if (subject.getPrincipal() == null) {// 表示没有登录,重定向到登录页面
saveRequest(request);
WebUtils.issueRedirect(request, response, LOGIN_URL);
} else {
Principal principal = (com.lwj.modules.shiro.realm.Principal) subject.getPrincipal();
if (principal.getChangedPassword() == null || !principal.getChangedPassword()) {
if (StringUtils.hasText(NEW_PASSWORD_URL)) {// 如果首次登录未修改密码,则跳转到修改密码页面
WebUtils.issueRedirect(request, response, NEW_PASSWORD_URL);
} else {
WebUtils.toHttp(response).sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
}
}
return true;
} }

补充Principal类,这个类在登录的时候用于用户的认证,相当于保存当前登录用户的基本信息。

package com.lwj.modules.shiro.realm;

import java.io.Serializable;

/**
*
* @Description :身份信息
* @author : lwj
* @version : 1.0.0
* @Date :2016-11-13 11:21:56
*/
public class Principal implements Serializable { /** 用户Cookie名称 */
public static final String USER_COOKIE_NAME = "u_c_n"; /** "身份信息"参数名称 */
public static final String PRINCIPAL_ATTRIBUTE_NAME = Principal.class.getName() + ".PRINCIPAL";
/**
*
*/
private static final long serialVersionUID = 1L; /** ID */
private Integer id; /** 用户名 */
private String username;/**
* 角色ID
*/
private Integer roleId;
  /**
* 登录IP
*/
private String ip;/**
* 第一次登陆是否修改密码(平台)
*/
private Boolean changedPassword; /**
* @param id
* ID
* @param username
* 用户名
*/
public Principal(Integer id, String username,Boolean changedPassword, Integer roleId, String ip) {
this.id = id;
this.username = username;
     this.changedPassword = changedPassword;
this.roleId = roleId;
     this.ip = ip;
} /**
* 获取ID
*
* @return ID
*/
public Integer getId() {
return id;
} /**
* 设置ID
*
* @param id
* ID
*/
public void setId(Integer id) {
this.id = id;
} /**
* 获取用户名
*
* @return 用户名
*/
public String getUsername() {
return username;
} /**
* 设置用户名
*
* @param username
* 用户名
*/
public void setUsername(String username) {
this.username = username;
} public Integer getRoleId() {
return roleId;
} public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
   public String getIp() {
return ip;
} public void setIp(String ip) {
this.ip = ip;
}   public Boolean getChangedPassword() {
return changedPassword;
} public void setChangedPassword(Boolean changedPassword) {
this.changedPassword = changedPassword;
} }

配置shiro.xml

  <!-- 自定义shiro的filter -->
<bean id="changedPassword" class="com.lwj.modules.filter.ChangePasswordFilter" /> <!-- shiroFilter -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的核心安全接口,这个属性是必须的 -->
<property name="securityManager" ref="securityManager" />
<!-- 要求登录时的链接 -->
<property name="loginUrl" value="/login.html" />
<!-- 登录成功后要跳转的链接 -->
<property name="successUrl" value="/" />
<!-- 用户访问未对其授权的资源时,所显示的链接 -->
<property name="unauthorizedUrl" value="/common/unauthorized.html" /> <property name="filterChainDefinitions">
<value><!-- 用户首次登录必须修改密码 -->
/index/* = changedPassword
/navigation/* = authc,changedPassword
/** = authc
</value>
</property>
<property name="filters">
<map>
<entry key="changedPassword" value-ref="changedPassword" />
</map>
</property>
</bean>

Shiro自定义过滤器的更多相关文章

  1. shiro 自定义过滤器,拦截过期session的请求,并且以ajax形式返回

    自定义过滤器: public class CustomFormAuthenticationFilter extends FormAuthenticationFilter { @Override pro ...

  2. shiro使用框架,自定义过滤器

    1.shiro配置文件配置 <!-- Shiro Filter --> <bean id="shiroFilter" class="org.apache ...

  3. Shiro自定义Realm时用注解的方式注入父类的credentialsMatcher

    用Shiro做登录权限控制时,密码加密是自定义的. 数据库的密码通过散列获取,如下,算法为:md5,盐为一个随机数字,散列迭代次数为3次,最终将salt与散列后的密码保存到数据库内,第二次登录时将登录 ...

  4. shiro的过滤器

    shiro的过滤器也是不多的我们可以自定义的方法,它的继承体系如下: 另外UserFilter是继承于AccessControlFilter 1.NameableFilter NameableFilt ...

  5. shiro自定义拦截url

    在实际项目上,我们针对不同的用户(guste,user,admin,mobile user)等等,需要进入不同的页面,比如,手机端用户需要进入Mobile/这个路径下的,这个时候,我们需要自定义拦截u ...

  6. Shiro 自定义登陆、授权、拦截器

    Shiro 登陆.授权.拦截 按钮权限控制 一.目标 Maven+Spring+shiro 自定义登陆.授权 自定义拦截器 加载数据库资源构建拦截链 使用总结: 1.需要设计的数据库:用户.角色.权限 ...

  7. 解决shiro自定义filter后,ajax登录无法登录,并且无法显示静态资源的问题

    这个问题困扰了我一天,看了下面两个文章,豁然开朗: https://www.cnblogs.com/gj1990/p/8057348.html https://412887952-qq-com.ite ...

  8. 实现MVC自定义过滤器,自定义Area过滤器,自定义Controller,Action甚至是ViewData过滤器

    MVC开发中几种以AOP方式实现的Filters是非常好用的,默认情况下,我们通过App_Start中的FilterConfig来实现的过滤器注册是全局的,也就是整个应用程序都会使用的,针对单独的Fi ...

  9. lucene自定义过滤器

    先介绍下查询与过滤的区别和联系,其实查询(各种Query)和过滤(各种Filter)之间非常相似,可以这样说只要用Query能完成的事,用过滤也都可以完成,它们之间可以相互转换,最大的区别就是使用过滤 ...

随机推荐

  1. Java读取Txt封装到对象中——(三)

    JavaBean package bean; public class Question { private String timu; //题干 private String leixing; //类 ...

  2. linux 下安装 oracle

    http://yourcouner.blog.51cto.com/59520/91156 一.RedHat AS4系统安装: 磁盘配置: 设备 类型 大小 / ext3 39911 swap 1024 ...

  3. Linux组管理和权限管理

    ⒈Linux组基本介绍 1)在Linux中的每个用户必须属于一个组,不能独立于组外. 2)Linux中每个文件都有所有者.所在组.其它组的概念 ①所有者 一般(默认)为文件的创建者,谁创建了该文件,就 ...

  4. 【转】Python之数据序列化(json、pickle、shelve)

    [转]Python之数据序列化(json.pickle.shelve) 本节内容 前言 json模块 pickle模块 shelve模块 总结 一.前言 1. 现实需求 每种编程语言都有各自的数据类型 ...

  5. linux windows 共享文件夹

    1.首先在windows上共享一个目录,如:共享了目录share,用户和密码都是:massky 2.在linux机器上,在/mnt目录下建立一个ml45目录,使用root用户,执行下面命令: moun ...

  6. aliyun添加数据盘parted方式分区格式化和lvm挂载及数据盘的扩容

    一.普通磁盘分区管理方式 1.对磁盘进行分区 列出磁盘 # fdisk -l # fdisk /dev/vdb Welcome to fdisk (util-linux 2.23.2). Change ...

  7. dellR720服务器设置光盘引导流程安装cenos7

    1.开机,按F10,进入系统引导界面,选择加载系统选项,并选择redhat 7.1选项 系统提示不支持,选择仍然继续,根据提示设置BIOS设置启动,重启 2.根据提示按F11进入BIOS启动设置,选择 ...

  8. docker 定时清理none镜像

    =============================================== 2019/3/31_第1次修改                       ccb_warlock == ...

  9. [学习笔记]Javascript采用二进制浮点数和四舍五入的错误

    1.样例 var a = .3 - .2 //0.09999999999999998 var b = .2 - .1 //0.1 a == b //false 出现这样的原因在于 1.Javascri ...

  10. opencv error: insufficient memory错误解决办法

    用opencv合成图像时出现的错误,大概4000多张会报错,在网上查阅一些博客时才知道原因.之前编译的时候用的是x86,切换到x64下可解决问题,具体: 1.项目->属性->配置管理器-& ...