项目中需要所有首次登录的用户必须修改密码才可使用系统,项目采用的是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. python cookbook 笔记一

    因为有些代码只有在python3里可以正常运行,所以最好配两个虚拟环境 安装虚拟环境: pip install virtualenv virtualenv -p /usr/bin/python3.5 ...

  2. Debian ifconfig 命令找不到

    如何配置让 Debian 非特权用户也可以使用 ifconfig . ifconfig 在 /sbin 目录下,新建一个用户时, Debian 默认从 /etc/skel/ 复制配置文件, /sbin ...

  3. SpringBoot整合MyBatis(XML)

    (1).添加依赖 <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId> ...

  4. 七、Sparse Autoencoder介绍

    目前为止,我们已经讨论了神经网络在有监督学习中的应用.在有监督学习中,训练样本是有类别标签的.现在假设我们只有一个没有带类别标签的训练样本集合  ,其中  .自编码神经网络是一种无监督学习算法,它使用 ...

  5. 一个有趣的小例子,带你入门协程模块-asyncio

    一个有趣的小例子,带你入门协程模块-asyncio 上篇文章写了关于yield from的用法,简单的了解异步模式,[https://www.cnblogs.com/c-x-a/p/10106031. ...

  6. 『实践』Matlab实现Flyod求最短距离及存储最优路径

    Matlab实现Flyod求最短距离及存储最优路径 一.实际数据 已知图中所有节点的X.Y坐标. 图中的节点编号:矩阵中的编号 J01-J62:1-62; F01-F60:63-122; Z01-Z0 ...

  7. Expm 9_1 有向图中环的判断问题

    [问题描述] 给定一个有向图,要求使用深度优先搜索策略,判断图中是否存在环. package org.xiu68.exp.exp9; public class Exp9_1 { //用深度优先搜索判断 ...

  8. redhat5 设置静态ip

    Last login: Sat Oct 14 16:19:13 2017 # 进入ip凭证文件设置地方 [root@oracle ~]# cd /etc/sysconfig/network-scrip ...

  9. Eclipse开发环境配置

    1. java环境 安装 本系统使用java6开发,老师使用1.6.0 _45版本开发,如下图所示: "开发工具"目录提供了1.6.0 _45版本32位和64位两个安装程序,大家根 ...

  10. JavaScript中的短路

    短路:逻辑运算从左到右.逻辑或运算,当左边的条件成立时,后面的条件将不再参与运算. 因此在逻辑或运算中,尽量将条件结果为true的放第一位.而在逻辑与运算中,尽量将条件结果为false的放到第一位. ...