Shiro教程、验证码kaptcha、successUrl不跳转问题解决

shiro教程http://jinnianshilongnian.iteye.com/blog/2018398
验证码kaptchahttp://aperise.iteye.com/blog/2276496

FormAuthenticationFilter

的successUrl不跳转问题

http://aperise.iteye.com/blog/2276496

1.shiro教程

  shiro教程参见这篇博客,讲解的太细了,也讲的非常到位,望尘莫及,膜拜膜拜!

  《跟我学Shiro》教程   http://jinnianshilongnian.iteye.com/blog/2018398

第一章  Shiro简介http://jinnianshilongnian.iteye.com/blog/2018936
第二章  身份验证http://jinnianshilongnian.iteye.com/blog/2019547
第三章  授权http://jinnianshilongnian.iteye.com/blog/2020017
第四章  INI配置http://jinnianshilongnian.iteye.com/blog/2020820
第五章  编码/加密http://jinnianshilongnian.iteye.com/blog/2021439
第六章  Realm及相关对象http://jinnianshilongnian.iteye.com/blog/2022468
第七章  与Web集成http://jinnianshilongnian.iteye.com/blog/2024723
第八章 拦截器机制http://jinnianshilongnian.iteye.com/blog/2025656
第九章 JSP标签http://jinnianshilongnian.iteye.com/blog/2026398
第十章  会话管理http://jinnianshilongnian.iteye.com/blog/2028675
第十一章  缓存机制http://jinnianshilongnian.iteye.com/blog/2029217
第十二章  与Spring集成http://jinnianshilongnian.iteye.com/blog/2029717
第十三章  RememberMehttp://jinnianshilongnian.iteye.com/blog/2031823
第十四章  SSLhttp://jinnianshilongnian.iteye.com/blog/2036420
第十五章  单点登录http://jinnianshilongnian.iteye.com/blog/2036730
第十六章  综合实例http://jinnianshilongnian.iteye.com/blog/2037222
第十七章  OAuth2集成http://jinnianshilongnian.iteye.com/blog/2038646
第十八章 并发登录人数控制http://jinnianshilongnian.iteye.com/blog/2039760
第十九章 动态URL权限控制http://jinnianshilongnian.iteye.com/blog/2040929
第二十章 无状态Web应用集成http://jinnianshilongnian.iteye.com/blog/2041909
第二十一章 授予身份及切换身份http://jinnianshilongnian.iteye.com/blog/2044616
第二十二章 集成验证码http://jinnianshilongnian.iteye.com/blog/2046041
第二十三章 多项目集中权限管理及分布式会话http://jinnianshilongnian.iteye.com/blog/2047168
第二十四章 在线会话管理http://jinnianshilongnian.iteye.com/blog/2047643

2.shiro中增加验证码kaptcha

  2.1 增加对于kaptcha的maven依赖

		<!-- kaptcha验证码 -->
		<dependency>
			<version>0.0.9</version>
			<groupId>com.github.axet</groupId>
			<artifactId>kaptcha</artifactId>
		</dependency>
 

  2.2 web.xml中增加kaptcha servlet拦截

	<!-- kaptcha验证码 -->
	<servlet>
		<servlet-name>kaptcha</servlet-name>
		<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
		<init-param>
			<param-name>kaptcha.noise.impl</param-name>
			<param-value>com.google.code.kaptcha.impl.NoNoise</param-value>
		</init-param>
		<!-- 验证码图片是否有边框 -->
		<init-param>
			<param-name>kaptcha.border</param-name>
			<param-value>yes</param-value>
		</init-param>
		<!-- 验证码图片宽度 -->
		<init-param>
			<param-name>kaptcha.image.width</param-name>
			<param-value>100</param-value>
		</init-param>
		<!-- 验证码图片高度 -->
		<init-param>
			<param-name>kaptcha.image.height</param-name>
			<param-value>50</param-value>
		</init-param>
		<!-- 图片上验证码位数 -->
		<init-param>
			<param-name>kaptcha.textproducer.char.length</param-name>
			<param-value>4</param-value>
		</init-param>
	</servlet>
	<!-- 拦截request路径为/kaptcha.jpg的请求,然后调用kaptcha产生验证码 -->
	<servlet-mapping>
		<servlet-name>kaptcha</servlet-name>
		<url-pattern>/kaptcha.jpg</url-pattern>
	</servlet-mapping>
 

  2.3 login.jsp页面增加验证码功能

<script type="text/javascript">
var captcha;
function refreshCaptcha(){  
    document.getElementById("img_kaptcha").src="${contextPath}/kaptcha.jpg?t=" + Math.random();  
} 
</script>
	<li>
		<label for="username">用户名:</label>
		<input type="text" name="username" class="login_input" id="username" />
	</li>
	<li>
		<label for="password">密码:</label>
		<input type="password" name="password" class="login_input" id="password" autocomplete="off" />
	</li>
	<li>
 		<label for="kaptcha">验证码:</label>
		<input type="text" name="kaptcha"  class="login_input_kaptcha" id="kaptcha" autocomplete="off" />
		<img   class="login_input_kaptcha_img" alt="验证码" src="${contextPath}/kaptcha.jpg" title="点击更换" id="img_kaptcha"  onclick="javascript:refreshCaptcha();" />
	</li>
 

  2.4 shiro配置里实现一个自己的AccessControlFilter类KaptchaFilter

public class KaptchaFilter extends AccessControlFilter {
	private String kaptchaParam = "kaptcha";// 前台提交的验证码参数名

	public String getKaptchaParam() {
		return kaptchaParam;
	}

	public void setKaptchaParam(String kaptchaParam) {
		this.kaptchaParam = kaptchaParam;
	}

	@Override
	protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
			throws Exception {
		HttpServletRequest httpServletRequest = WebUtils.toHttp(request);
		// 验证验证码是否正确
		if (null == request.getParameter(kaptchaParam)) {
			return true;
		} else {
			String kaptchaFromWeb = (String) request.getParameter(kaptchaParam);
			String kaptchaFromSession = (String) httpServletRequest.getSession().getAttribute(Constants.KAPTCHA_SESSION_KEY);
			return kaptchaFromSession.toUpperCase().equals(kaptchaFromWeb.toUpperCase());
		}
	}

	@Override
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
		// 如果验证码失败了,存储失败key属性
		request.setAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME, "Kaptcha.error");
		return true;
	}
}
 

  2.5 重写自己的FormAuthenticationFilter为KaptchaFormAuthenticationFilter

public class KaptchaFormAuthenticationFilter extends FormAuthenticationFilter {
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
		if (request.getAttribute(getFailureKeyAttribute()) != null) {
			return true;
		}
		return super.onAccessDenied(request, response, mappedValue);
	}

	@Override
	protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,ServletResponse response) throws Exception {
		WebUtils.issueRedirect(request, response, getSuccessUrl());
		return false;
	}
}
 

  2.6 shiro配置里修改如下

	<!-- 基于Form表单的身份验证过滤器 -->
	<bean id="formAuthenticationFilter" class="com.xxx.shrio.filter.KaptchaFormAuthenticationFilter">
		<property name="usernameParam" value="username" />
		<property name="passwordParam" value="password" />
		<property name="rememberMeParam" value="rememberMe" />
		<property name="loginUrl" value="/login" />
        <property name="successUrl" value="/index"/>
	</bean>
<bean id="kaptchaFilter" class="com.xxx.shrio.filter.KaptchaFilter">
		<property name="kaptchaParam" value="kaptcha" />
	</bean>  

    <!-- Shiro的Web过滤器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager"/>
        <property name="loginUrl" value="/login"/>
        <property name="successUrl" value="/index"/>
        <property name="unauthorizedUrl" value="/redirect"/>
        <property name="filters">
            <util:map>
				<entry key="authc" value-ref="formAuthenticationFilter" />
				<entry key="sysUser" value-ref="sysUserFilter" />
				<entry key="kaptcha" value-ref="kaptchaFilter" />
            </util:map>
        </property>
        <property name="filterChainDefinitions">
            <value>
            	/login = kaptcha,authc
            	/unauthorized.jsp = authc
            	/redirect = anon
            	/css/** = anon
            	/js/** = anon
            	/img/** = anon
            	/kaptcha.jpg = anon
            	/** = user,sysUser
            </value>
        </property>
    </bean>
 

  2.7 最后验证码添加后效果


 

3.shiro的FormAuthenticationFilter的successUrl不跳转问题

  3.1 首先查看shiro源代码WebUtils类里方法

/**
     * Redirects the to the request url from a previously
     * {@link #saveRequest(javax.servlet.ServletRequest) saved} request, or if there is no saved request, redirects the
     * end user to the specified {@code fallbackUrl}.  If there is no saved request or fallback url, this method
     * throws an {@link IllegalStateException}.
     * <p/>
     * This method is primarily used to support a common login scenario - if an unauthenticated user accesses a
     * page that requires authentication, it is expected that request is
     * {@link #saveRequest(javax.servlet.ServletRequest) saved} first and then redirected to the login page. Then,
     * after a successful login, this method can be called to redirect them back to their originally requested URL, a
     * nice usability feature.
     *
     * @param request     the incoming request
     * @param response    the outgoing response
     * @param fallbackUrl the fallback url to redirect to if there is no saved request available.
     * @throws IllegalStateException if there is no saved request and the {@code fallbackUrl} is {@code null}.
     * @throws IOException           if there is an error redirecting
     * @since 1.0
     */
    public static void redirectToSavedRequest(ServletRequest request, ServletResponse response, String fallbackUrl)
            throws IOException {
        String successUrl = null;
        boolean contextRelative = true;
        SavedRequest savedRequest = WebUtils.getAndClearSavedRequest(request);
        if (savedRequest != null && savedRequest.getMethod().equalsIgnoreCase(AccessControlFilter.GET_METHOD)) {
            successUrl = savedRequest.getRequestUrl();
            contextRelative = false;
        }

        if (successUrl == null) {
            successUrl = fallbackUrl;
        }

        if (successUrl == null) {
            throw new IllegalStateException("Success URL not available via saved request or via the " +
                    "successUrlFallback method parameter. One of these must be non-null for " +
                    "issueSuccessRedirect() to work.");
        }

        WebUtils.issueRedirect(request, response, successUrl, null, contextRelative);
    }
     首先通过SavedRequest savedRequest = WebUtils.getAndClearSavedRequest(request);

从session中获取到第一次请求时的地址,然后通过successUrl = savedRequest.getRequestUrl();

将FormAuthenticationFilter配置的successUrl值覆盖掉所以shiro默认跳转到了首次请求的url了。

 

  3.2 shiro的FormAuthenticationFilter的successUrl不跳转问题解决

    重写自己的FormAuthenticationFilter类KaptchaFormAuthenticationFilter,主要是覆盖里面的方法onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,ServletResponse response),代码如下:

public class KaptchaFormAuthenticationFilter extends FormAuthenticationFilter {
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
		if (request.getAttribute(getFailureKeyAttribute()) != null) {
			return true;
		}
		return super.onAccessDenied(request, response, mappedValue);
	}

	@Override
	protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request,ServletResponse response) throws Exception {
		WebUtils.issueRedirect(request, response, getSuccessUrl());
		return false;
	}
}
    然后覆盖shiro配置:
	<!-- 基于Form表单的身份验证过滤器 -->
	<bean id="formAuthenticationFilter" class="com.xxx.shrio.filter.KaptchaFormAuthenticationFilter">
		<property name="usernameParam" value="username" />
		<property name="passwordParam" value="password" />
		<property name="rememberMeParam" value="rememberMe" />
		<property name="loginUrl" value="/login" />
        <property name="successUrl" value="/index"/>
	</bean>
    这样, shiro登录成功后只会跳转到FormAuthenticationFilter配置的successUrl这个地址。

4.shiro集成spring 4.x和quartz 2.x报错java.lang.InstantiationError: org.quartz.SimpleTrigger

    shiro集成spring 4.x和quartz 2.x报错java.lang.InstantiationError: org.quartz.SimpleTrigger,主要原因是shiro的org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler是对quartz1.x的实现,但是quartz2.x已经变动很大,导致整合quartz2.x时候,shiro原来对于shiro的实现不可用 ,解决办法如下:

    4.1 自己实现quartz2.x的org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler

    shiro对于quartz1.x的实现如下:

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.shiro.session.mgt.quartz;

import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleTrigger;
import org.quartz.impl.StdSchedulerFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.SessionValidationScheduler;
import org.apache.shiro.session.mgt.ValidatingSessionManager;


/**
 * An implementation of the {@link org.apache.shiro.session.mgt.SessionValidationScheduler SessionValidationScheduler} that uses Quartz to schedule a
 * job to call {@link org.apache.shiro.session.mgt.ValidatingSessionManager#validateSessions()} on
 * a regular basis.
 *
 * @since 0.1
 */
public class QuartzSessionValidationScheduler implements SessionValidationScheduler {

    //TODO - complete JavaDoc

    /*--------------------------------------------
    |             C O N S T A N T S             |
    ============================================*/
    /**
     * The default interval at which sessions will be validated (1 hour);
     * This can be overridden by calling {@link #setSessionValidationInterval(long)}
     */
    public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL;

    /**
     * The name assigned to the quartz job.
     */
    private static final String JOB_NAME = "SessionValidationJob";

    /*--------------------------------------------
    |    I N S T A N C E   V A R I A B L E S    |
    ============================================*/
    private static final Logger log = LoggerFactory.getLogger(QuartzSessionValidationScheduler.class);

    /**
     * The configured Quartz scheduler to use to schedule the Quartz job.  If no scheduler is
     * configured, the scheduler will be retrieved by calling {@link StdSchedulerFactory#getDefaultScheduler()}
     */
    private Scheduler scheduler;

    private boolean schedulerImplicitlyCreated = false;

    private boolean enabled = false;

    /**
     * The session manager used to validate sessions.
     */
    private ValidatingSessionManager sessionManager;

    /**
     * The session validation interval in milliseconds.
     */
    private long sessionValidationInterval = DEFAULT_SESSION_VALIDATION_INTERVAL;

    /*--------------------------------------------
    |         C O N S T R U C T O R S           |
    ============================================*/

    /**
     * Default constructor.
     */
    public QuartzSessionValidationScheduler() {
    }

    /**
     * Constructor that specifies the session manager that should be used for validating sessions.
     *
     * @param sessionManager the <tt>SessionManager</tt> that should be used to validate sessions.
     */
    public QuartzSessionValidationScheduler(ValidatingSessionManager sessionManager) {
        this.sessionManager = sessionManager;
    }

    /*--------------------------------------------
    |  A C C E S S O R S / M O D I F I E R S    |
    ============================================*/

    protected Scheduler getScheduler() throws SchedulerException {
        if (scheduler == null) {
            scheduler = StdSchedulerFactory.getDefaultScheduler();
            schedulerImplicitlyCreated = true;
        }
        return scheduler;
    }

    public void setScheduler(Scheduler scheduler) {
        this.scheduler = scheduler;
    }

    public void setSessionManager(ValidatingSessionManager sessionManager) {
        this.sessionManager = sessionManager;
    }

    public boolean isEnabled() {
        return this.enabled;
    }

    /**
     * Specifies how frequently (in milliseconds) this Scheduler will call the
     * {@link org.apache.shiro.session.mgt.ValidatingSessionManager#validateSessions() ValidatingSessionManager#validateSessions()} method.
     *
     * <p>Unless this method is called, the default value is {@link #DEFAULT_SESSION_VALIDATION_INTERVAL}.
     *
     * @param sessionValidationInterval
     */
    public void setSessionValidationInterval(long sessionValidationInterval) {
        this.sessionValidationInterval = sessionValidationInterval;
    }

    /*--------------------------------------------
    |               M E T H O D S               |
    ============================================*/

    /**
     * Starts session validation by creating a Quartz simple trigger, linking it to
     * the {@link QuartzSessionValidationJob}, and scheduling it with the Quartz scheduler.
     */
    public void enableSessionValidation() {

        if (log.isDebugEnabled()) {
            log.debug("Scheduling session validation job using Quartz with " +
                    "session validation interval of [" + sessionValidationInterval + "]ms...");
        }

        try {
            SimpleTrigger trigger = new SimpleTrigger(getClass().getName(),
                    Scheduler.DEFAULT_GROUP,
                    SimpleTrigger.REPEAT_INDEFINITELY,
                    sessionValidationInterval);

            JobDetail detail = new JobDetail(JOB_NAME, Scheduler.DEFAULT_GROUP, QuartzSessionValidationJob.class);
            detail.getJobDataMap().put(QuartzSessionValidationJob.SESSION_MANAGER_KEY, sessionManager);

            Scheduler scheduler = getScheduler();

            scheduler.scheduleJob(detail, trigger);
            if (schedulerImplicitlyCreated) {
                scheduler.start();
                if (log.isDebugEnabled()) {
                    log.debug("Successfully started implicitly created Quartz Scheduler instance.");
                }
            }
            this.enabled = true;

            if (log.isDebugEnabled()) {
                log.debug("Session validation job successfully scheduled with Quartz.");
            }

        } catch (SchedulerException e) {
            if (log.isErrorEnabled()) {
                log.error("Error starting the Quartz session validation job.  Session validation may not occur.", e);
            }
        }
    }

    public void disableSessionValidation() {
        if (log.isDebugEnabled()) {
            log.debug("Stopping Quartz session validation job...");
        }

        Scheduler scheduler;
        try {
            scheduler = getScheduler();
            if (scheduler == null) {
                if (log.isWarnEnabled()) {
                    log.warn("getScheduler() method returned a null Quartz scheduler, which is unexpected.  Please " +
                            "check your configuration and/or implementation.  Returning quietly since there is no " +
                            "validation job to remove (scheduler does not exist).");
                }
                return;
            }
        } catch (SchedulerException e) {
            if (log.isWarnEnabled()) {
                log.warn("Unable to acquire Quartz Scheduler.  Ignoring and returning (already stopped?)", e);
            }
            return;
        }

        try {
            scheduler.unscheduleJob(JOB_NAME, Scheduler.DEFAULT_GROUP);
            if (log.isDebugEnabled()) {
                log.debug("Quartz session validation job stopped successfully.");
            }
        } catch (SchedulerException e) {
            if (log.isDebugEnabled()) {
                log.debug("Could not cleanly remove SessionValidationJob from Quartz scheduler.  " +
                        "Ignoring and stopping.", e);
            }
        }

        this.enabled = false;

        if (schedulerImplicitlyCreated) {
            try {
                scheduler.shutdown();
            } catch (SchedulerException e) {
                if (log.isWarnEnabled()) {
                    log.warn("Unable to cleanly shutdown implicitly created Quartz Scheduler instance.", e);
                }
            } finally {
                setScheduler(null);
                schedulerImplicitlyCreated = false;
            }
        }
    }
}

    现在自己更改这个实现如下:

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.xxx.shiro.session.mgt.quartz;

import org.apache.shiro.session.mgt.DefaultSessionManager;
import org.apache.shiro.session.mgt.SessionValidationScheduler;
import org.apache.shiro.session.mgt.ValidatingSessionManager;
import org.apache.shiro.session.mgt.quartz.QuartzSessionValidationJob;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * An implementation of the {@link org.apache.shiro.session.mgt.SessionValidationScheduler SessionValidationScheduler} that uses Quartz to schedule a
 * job to call {@link org.apache.shiro.session.mgt.ValidatingSessionManager#validateSessions()} on
 * a regular basis.
 *
 * @since 0.1
 */
public class QuartzSessionValidationScheduler implements SessionValidationScheduler {

    //TODO - complete JavaDoc

    /*--------------------------------------------
    |             C O N S T A N T S             |
    ============================================*/
    /**
     * The default interval at which sessions will be validated (1 hour);
     * This can be overridden by calling {@link #setSessionValidationInterval(long)}
     */
    public static final long DEFAULT_SESSION_VALIDATION_INTERVAL = DefaultSessionManager.DEFAULT_SESSION_VALIDATION_INTERVAL;

    /**
     * The name assigned to the quartz job.
     */
    private static final String JOB_NAME = "SessionValidationJob";

    /*--------------------------------------------
    |    I N S T A N C E   V A R I A B L E S    |
    ============================================*/
    private static final Logger log = LoggerFactory.getLogger(QuartzSessionValidationScheduler.class);

    /**
     * The configured Quartz scheduler to use to schedule the Quartz job.  If no scheduler is
     * configured, the scheduler will be retrieved by calling {@link StdSchedulerFactory#getDefaultScheduler()}
     */
    private Scheduler scheduler;

    private boolean schedulerImplicitlyCreated = false;

    private boolean enabled = false;

    /**
     * The session manager used to validate sessions.
     */
    private ValidatingSessionManager sessionManager;

    /**
     * The session validation interval in milliseconds.
     */
    private long sessionValidationInterval = DEFAULT_SESSION_VALIDATION_INTERVAL;

    /*--------------------------------------------
    |         C O N S T R U C T O R S           |
    ============================================*/

    /**
     * Default constructor.
     */
    public QuartzSessionValidationScheduler() {
    }

    /**
     * Constructor that specifies the session manager that should be used for validating sessions.
     *
     * @param sessionManager the <tt>SessionManager</tt> that should be used to validate sessions.
     */
    public QuartzSessionValidationScheduler(ValidatingSessionManager sessionManager) {
        this.sessionManager = sessionManager;
    }

    /*--------------------------------------------
    |  A C C E S S O R S / M O D I F I E R S    |
    ============================================*/

    protected Scheduler getScheduler() throws SchedulerException {
        if (scheduler == null) {
            scheduler = StdSchedulerFactory.getDefaultScheduler();
            schedulerImplicitlyCreated = true;
        }
        return scheduler;
    }

    public void setScheduler(Scheduler scheduler) {
        this.scheduler = scheduler;
    }

    public void setSessionManager(ValidatingSessionManager sessionManager) {
        this.sessionManager = sessionManager;
    }

    public boolean isEnabled() {
        return this.enabled;
    }

    /**
     * Specifies how frequently (in milliseconds) this Scheduler will call the
     * {@link org.apache.shiro.session.mgt.ValidatingSessionManager#validateSessions() ValidatingSessionManager#validateSessions()} method.
     *
     * <p>Unless this method is called, the default value is {@link #DEFAULT_SESSION_VALIDATION_INTERVAL}.
     *
     * @param sessionValidationInterval
     */
    public void setSessionValidationInterval(long sessionValidationInterval) {
        this.sessionValidationInterval = sessionValidationInterval;
    }

    /*--------------------------------------------
    |               M E T H O D S               |
    ============================================*/

    /**
     * Starts session validation by creating a Quartz simple trigger, linking it to
     * the {@link QuartzSessionValidationJob}, and scheduling it with the Quartz scheduler.
     */
    public void enableSessionValidation() {

        if (log.isDebugEnabled()) {
            log.debug("Scheduling session validation job using Quartz with " +
                    "session validation interval of [" + sessionValidationInterval + "]ms...");
        }

        try {
/*            SimpleTrigger trigger = new SimpleTrigger(getClass().getName(),
                    Scheduler.DEFAULT_GROUP,
                    SimpleTrigger.REPEAT_INDEFINITELY,
                    sessionValidationInterval);

            JobDetail detail = new JobDetail(JOB_NAME, Scheduler.DEFAULT_GROUP, QuartzSessionValidationJob.class);
            detail.getJobDataMap().put(QuartzSessionValidationJob.SESSION_MANAGER_KEY, sessionManager);*/

        	//modify by xxx at 2017-07-25 10:55,shiro对于quartz2的实现更改
            SimpleTrigger trigger = TriggerBuilder  
                    .newTrigger()  
                    .startNow()  
                    .withIdentity(JOB_NAME, Scheduler.DEFAULT_GROUP)  
                    .withSchedule(  
                            SimpleScheduleBuilder.simpleSchedule()  
                                    .withIntervalInMilliseconds(  
                                            sessionValidationInterval)).build();  
  
            JobDetail detail = JobBuilder  
                    .newJob(QuartzSessionValidationJob.class)  
                    .withIdentity(JOB_NAME, Scheduler.DEFAULT_GROUP).build();  
            detail.getJobDataMap().put("sessionManager", this.sessionManager);  

            Scheduler scheduler = getScheduler();

            scheduler.scheduleJob(detail, trigger);
            if (schedulerImplicitlyCreated) {
                scheduler.start();
                if (log.isDebugEnabled()) {
                    log.debug("Successfully started implicitly created Quartz Scheduler instance.");
                }
            }
            this.enabled = true;

            if (log.isDebugEnabled()) {
                log.debug("Session validation job successfully scheduled with Quartz.");
            }

        } catch (SchedulerException e) {
            if (log.isErrorEnabled()) {
                log.error("Error starting the Quartz session validation job.  Session validation may not occur.", e);
            }
        }
    }

    public void disableSessionValidation() {
        if (log.isDebugEnabled()) {
            log.debug("Stopping Quartz session validation job...");
        }

        Scheduler scheduler;
        try {
            scheduler = getScheduler();
            if (scheduler == null) {
                if (log.isWarnEnabled()) {
                    log.warn("getScheduler() method returned a null Quartz scheduler, which is unexpected.  Please " +
                            "check your configuration and/or implementation.  Returning quietly since there is no " +
                            "validation job to remove (scheduler does not exist).");
                }
                return;
            }
        } catch (SchedulerException e) {
            if (log.isWarnEnabled()) {
                log.warn("Unable to acquire Quartz Scheduler.  Ignoring and returning (already stopped?)", e);
            }
            return;
        }

        try {
            /*scheduler.unscheduleJob(JOB_NAME, Scheduler.DEFAULT_GROUP);*/
        	//modify by xxx at 2017-07-25 10:55,shiro对于quartz2的实现更改
            scheduler.unscheduleJob(new TriggerKey(JOB_NAME,  Scheduler.DEFAULT_GROUP));  

            if (log.isDebugEnabled()) {
                log.debug("Quartz session validation job stopped successfully.");
            }
        } catch (SchedulerException e) {
            if (log.isDebugEnabled()) {
                log.debug("Could not cleanly remove SessionValidationJob from Quartz scheduler.  " +
                        "Ignoring and stopping.", e);
            }
        }

        this.enabled = false;

        if (schedulerImplicitlyCreated) {
            try {
                scheduler.shutdown();
            } catch (SchedulerException e) {
                if (log.isWarnEnabled()) {
                    log.warn("Unable to cleanly shutdown implicitly created Quartz Scheduler instance.", e);
                }
            } finally {
                setScheduler(null);
                schedulerImplicitlyCreated = false;
            }
        }
    }
}

 

    4.2 更改配置为自己的实现

	<!-- 会话验证调度器 -->
	<bean id="sessionValidationScheduler"
		class="com.xxx.shiro.session.mgt.quartz.QuartzSessionValidationScheduler">
		<property name="sessionValidationInterval" value="1800000" />
		<property name="sessionManager" ref="sessionManager" />
	</bean>

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值