• Shiro自定义过滤器


    项目中需要所有首次登录的用户必须修改密码才可使用系统,项目采用的是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>
  • 相关阅读:
    今天开始学习WCF了开发环境的配置
    我的文章《DLL封装登录框架实现代码复用》终于要发表了
    python小练习给右键菜单添加用chrome打开
    手动创建oracle数据库
    Sublime Text 2中如何输入中文
    转 用Python画Mandelbrot集
    Win7 64位安装Python PIL库
    推荐一本有关设计的好书《写给大家看的设计书》
    坚持做自己
    更新专业版显卡驱动导致ubuntu无法进入桌面环境
  • 原文地址:https://www.cnblogs.com/lyxy/p/6694387.html
Copyright © 2020-2023  润新知