Apache Shiro:如何强制更改密码?

时间:2014-06-16 12:32:08

标签: jsf-2.2 shiro

我已经运行了Java EE 7(JSF,JPA)和基于CDI的应用程序,使用Shiro进行身份验证和授权。

我已经满足要求,用户必须在一定时间后更改密码(可由应用程序的管理员自定义,即30天)。在我们的用户表中,我们存储了上次设置密码时的信息,因此可以在登录时计算,如果有时间的话。

计划是重新显示登录页面并表示不同的表单(更改密码而不是登录)。到现在为止还挺好。然而: 如何强制更改密码而不让用户导航到其他页面?

是否有推荐(甚至是内置)解决方案?

我的想法是实现一个过滤器,它检查会话范围的登录对象是否需要重置PW。 希望是,这就像创建一个新的过滤器一样简单,在那里注入登录并检查标志的状态 - 并且只要flag为真/他没有更新他的pw,就将用户重定向到登录页面。 / p>

(我们已经有一个自定义的cdi识别EnvironmentLoaderListener来支持我们的JPA领域。)

新过滤器会落后于最后一行吗?

[urls]
/javax.faces.resource/** = anon
/layout.xhtml = anon
/css/** = anon
/login.xhtml = user
/logout.xhtml = logout
/** = user

所以我们有:

/** = user,pwresetfilter

欢迎提供有关详细信息和整体解决方案的建议。

2 个答案:

答案 0 :(得分:0)

您可以使用您的解决方案,但最好是这样:

  1. 你让自己的境界

    MyRealm extends AuthorizingRealm {
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        }
    }
    

    在doGetAuthenticationInfo中,如果需要更改密码,您将检查凭据并抛出异常。随意扩展目前正在使用的领域。

  2. 在您的EnvironmentLoaderListener中注册您的领域

  3. 最后你可能需要使用过滤器来重定向到正确的页面,或者如果你使用REST(比如Jersey),你可以有一个异常映射器,它将响应你的浏览器客户端

答案 1 :(得分:0)

我在验证后对OTP有类似的要求,我使用普通过滤器来过滤掉所有请求。 在use bean中使用lastPasswordChangedDate制作一个属性,或者根据需要使用isPasswordChangerequired。并在过滤器中进行比较。

我的简单otpFliter代码如下,但您可以根据需要制作自己的jsf等:

/**
 * Servlet Filter implementation class OTPFilter
 */
@WebFilter(urlPatterns = {"/*"},initParams={@WebInitParam(name="enabled",value="0")})
public class OTPFilter implements Filter {

    /**
     * Default constructor. 
     */

    boolean enabled=true;


    public OTPFilter() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        // TODO Auto-generated method stub
    }

    /**
     * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // TODO Auto-generated method stub
        // place your code here

        // pass the request along the filter chain
        //System.out.println(enabled);
            if(enabled){
            if(SecurityUtils.getSubject().getPrincipal()!=null){
                if(request instanceof HttpServletRequest ){
                    HttpSession session = ((HttpServletRequest) request).getSession();
                    LoggedInUser user =  (LoggedInUser) session.getAttribute("userinfo");
                    String url = ((HttpServletRequest) request).getRequestURL().toString();
                    //System.out.println("url is "+ url);

                    if( !url.contains("public") && !user.isOTPverified()){



                        if(user.getOTP() == null)
                            {
                                user.setOTP(OTPUtils.generateOTP());
                            }
                        //user.setOTPverified(true);                        
                        ((HttpServletRequest) request).getRequestDispatcher("OTP.jsp").forward(request, response);

                        return;
                    }
                }
            }


            }

        chain.doFilter(request, response);
    }

    /**
     * @see Filter#init(FilterConfig)
     */
    public void init(FilterConfig fConfig) throws ServletException {
        // TODO Auto-generated method stub
        //System.out.println("fConfig.getInitParameter :" + fConfig.getInitParameter("enabled"));
         enabled = fConfig.getInitParameter("enabled").equals("1");
    }

}