1.shiro教程
shiro教程参见这篇博客,讲解的太细了,也讲的非常到位,望尘莫及,膜拜膜拜!
《跟我学Shiro》教程 http://jinnianshilongnian.iteye.com/blog/2018398
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>
- 大小: 15.6 KB
分享到:
相关推荐
Apache Shiro是一款强大的...通过上述资源,你将能够逐步构建起对Shiro框架的全面认识,并具备在实际项目中应用Shiro解决安全问题的能力。记得结合实践来巩固理论,这样才能更好地理解和掌握Shiro的核心概念和用法。
在本文中,我们将探讨如何在SpringBoot项目中集成Shiro并实现登录时的验证码功能,以防止机器人自动刷登录。验证码是一种有效的手段,可以确保只有真实用户而非自动化程序能够完成登录过程。 首先,我们看到一个名...
这个项目组合"Spring MVC + Shiro + Kaptcha + Excel + Hibernate + Mail"提供了一套全面的技术栈,旨在实现这样的目标。以下是对这些技术组件的详细解释: 1. **Spring MVC**:Spring MVC是Spring框架的一个模块,...
本教程将带你深入理解 Shiro 的核心概念,并通过实际案例教你如何在 Java 应用中有效使用 Shiro。 一、Shiro 的核心组件 1. **认证**:Shiro 提供了身份验证(Authentication)机制,即用户登录的过程。它允许应用...
Shiro 是一个强大且易用的安全管理框架,Kaptcha 则用于生成验证码,防止自动化程序的恶意操作,而Struts2 是一个基于MVC设计模式的Web应用框架。以下是这三个框架的详细知识讲解: 1. Apache Shiro: - **简介**...
### Shiro教程知识点总结 #### 一、Shiro简介 - **Shiro**是一个由Apache提供的强大且易用的Java安全框架,它提供了全面的安全服务,包括认证、授权、密码管理和会话管理等功能。 - **特点**: - **简单易用**:...
张开涛的Shiro教程是Java开发者学习Shiro的一个很好的资源,它涵盖了Shiro的核心概念和实践应用。 1. **Shiro基础** - **认证**:Shiro的认证机制允许用户输入身份凭证(如用户名和密码),然后与存储在数据库或...
Apache Shiro 拥有活跃的社区,提供了丰富的文档和示例,开发者可以在社区中获取帮助,解决问题。 本教程将详细讲解Shiro的这些概念,并通过实例演示如何在实际项目中应用。通过学习,你可以掌握Shiro的使用,提升...
中间件:lombok shiro thymeleaf druid kaptcha 前端框架 Layui java基于SpringBoot框架的仓库管理ERP系统(源码+数据库) 后端框架:SpringBoot MyBatis Mysql(估计只能使用Mysql,因为sql语句运用了limit) ...
Shiro 的教程通常会涵盖这些核心概念,按照主题分章节进行介绍,如身份验证、授权、INI 配置、编码/加密、Realms 及相关对象、与Web 集成、拦截器机制、JSP 标签、会话管理、缓存机制、SSL、单点登录、综合实例、...
总结起来,Spring Boot简化了Java应用的开发流程,而Shiro则提供了全面的安全解决方案。通过学习这两者,开发者可以构建出高效、安全的Web应用。同时,这两本教程PDF将为初学者提供详尽的学习资源,帮助他们快速掌握...
Apache Shiro 不仅仅是一个简单的权限控制库,它还提供了用户认证(Authentication)、授权(Authorization)、加密(Cryptography)和会话管理(Session Management)等全面的安全管理功能。它的设计目标是使安全...
4. **会话管理**:讲述Shiro如何管理用户的会话,包括会话超时、分布式会话解决方案,以及如何处理会话固定攻击。 5. **加密服务**:解释Shiro提供的密码学工具,如散列、加密和编码,以及如何安全地存储敏感信息。...
- **社区支持**:Apache Shiro有活跃的社区和邮件列表,遇到问题可以寻求帮助。 通过这个Apache Shiro教程,你可以学习到如何构建安全的Java应用,了解Shiro的配置和用法,以及如何在实际项目中实施身份验证、授权...
"跟我学Shiro教程"这个资源显然是为了帮助学习者深入理解并掌握Shiro的核心概念和实际应用。 在Shiro的认证服务中,其主要目标是确认用户身份。这通常涉及用户登录过程,其中用户提供的凭证(如用户名和密码)被...
Shiro入门实例 Shiro入门教程 Shiro框架学习demo http://www.xttblog.com/?p=669 权限管理教程。Shiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能。 Shiro可以在任何环境下运行,小到最...