English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
一般的登录流程会有:用户名不存在,密码错误,验证码错误等..
在集成shiro后,应用程序的外部访问权限以及访问控制交给了shiro来管理。
shiro提供了两个主要功能:认证(Authentication)和授权(Authorization);认证的作用是证明自身可以访问,一般是用户名加密码,授权的作用是谁可以访问哪些资源,通过开发者自己的用户角色权限系统来控制。
shiro的会话管理和缓存管理不在本文范围内。
下面通过登录失败的处理流程来介绍springmvc与shiro的集成。
项目依赖:
依赖名称 | 版本 |
spring | 4.1.4.RELEASE |
shiro | 1.2.2 |
self4j | 1.7.5 |
log4j | 1.2.17 |
在web.xml里配置shiro
shiroFilter org.springframework.web.filter.DelegatingFilterProxy targetFilterLifecycle true shiroFilter /*
新建一个spring-context-shiro.xml配置shiro相关信息,使用spring加载
<?xml version='1.0' encoding='UTF-8'?> <beans xmlns='http://www.springframework.org/schema/beans'> xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:context='http://www.springframework.org/schema/context' xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd" default-lazy-init="true"> <description>Shiro Configuration</description> <!-- 安全认证过滤器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <property name="loginUrl" value="/sys/login" /> <property name="successUrl" value="/sys" /> <property name="filters"> <map> <!--自定义登录验证过滤器--> <entry key="authc" value-ref="formAuthenticationFilter" /> </map> </property> <property name="filterChainDefinitions"> <value> /sys/login = authc /sys/logout = logout /sys/** = user </value> </property> </bean> <!-- 定义 Shiro 主要业务对象 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="systemAuthorizingRealm" /> <property name="cacheManager" ref="shiroCacheManager" /> </bean> <!-- معدير إنشاء معرف الجلسة --> <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator"/> <!-- معدير الجلسة، يحدد وقت انتهاء الجلسة والتحفظ عليها --> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"/> <!-- وقت انتهاء الجلسة العالمي (بالميليسيوندات)، افتراضي 30 دقيقة --> <property name="globalSessionTimeout" value="1800000" /> <property name="sessionDAO" ref="sessionDAO"/> </bean> <!-- معدير التحقق من الجلسات، يتم تنفيذ التحقق كل 30 دقيقة --> <!-- <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler"> --> <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler"/> <property name="interval" value="1800000"/> <property name="sessionManager" ref="sessionManager"/> </bean> <!-- sessionDAO يحفظ معلومات التحقق --> <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO"/> <property name="activeSessionsCacheName" value="شرو-الجلسات-النشطة" /> <property name="cacheManager" ref="shiroCacheManager" /> <property name="sessionIdGenerator" ref="sessionIdGenerator"/> </bean> <!-- معلومات إذن المستخدم Cache، باستخدام EhCache --> <bean id="shiroCacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> <property name="cacheManager" ref="cacheManager" /> </bean> <!-- معالج حياة Shiro --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> <!-- فحص الأذونات على مستوى الطريقة باستخدام AOP --> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"> <property name="proxyTargetClass" value="true" /> </bean> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager" /> </bean> </beans>
إنشاء مرشح التحقق من الدخول LoginAuthenticationFilter.java
إدراج javax.servlet.ServletRequest; إدراج javax.servlet.ServletResponse; إدراج org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.web.util.WebUtils; استيراد أورج اسبرينج ستريتيجي سيرفيس; /** * تصفية التحقق من صحة النموذج (بما في ذلك رمز التحقق) */ @Service public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.FormAuthenticationFilter { public static final String DEFAULT_CAPTCHA_PARAM = "validateCode"; private String captchaParam = DEFAULT_CAPTCHA_PARAM; public String getCaptchaParam() { return captchaParam; } protected String getCaptcha(ServletRequest request) { return WebUtils.getCleanParam(request, getCaptchaParam()); } protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) { String username = getUsername(request); String password = getPassword(request); String locale = request.getParameter("locale"); if (password == null) { password = ""; } boolean rememberMe = isRememberMe(request); String host = getHost(request); String captcha = getCaptcha(request); return new UsernamePasswordToken(username, password.toCharArray(),locale, rememberMe, host, captcha); } }
ایجاد کلاس کارتکمال UsernamePasswordToken.java
پکاج کام چونهوي ويسيرفيس ماودولز سيسي.سيكريتي; /** /* کلاس کارتکمال کاربر و پسورد (شامل کد تأیید) */ پبلیک کلاس UsernamePasswordToken نمیتواند org.apache.shiro.authc.UsernamePasswordToken { private static final long serialVersionUID = 1L; پرایوئت ساختار رشته captcha; پرایوئت ساختار رشته locale; پبلیک ساختار رشته getCaptcha() { بازگشت captcha; } پبلیک بیانیه_خودداری setCaptcha(ساختار رشته captcha) { این.captcha = captcha; } پبلیک ساختار رشته getLocale() { بازگشت locale; } پبلیک بیانیه_خودداری setLocale(ساختار رشته locale) { این.locale = locale; } پبلیک کلاس UsernamePasswordToken() { سوپر(); } پبلیک کلاس UsernamePasswordToken(ساختار رشته نام_کاربری، آرایه کاراکتر پسورد، بولین remeberMe، ساختار رشته میزبان، ساختار رشته captcha) { سوپر(نام_کاربری، پسورد، یادآوری_من، میزبان); این.captcha = captcha; } پبلیک کلاس UsernamePasswordToken(ساختار رشته نام_کاربری، آرایه کاراکتر پسورد، ساختار رشته locale، بولین remeberMe، ساختار رشته میزبان، ساختار رشته captcha) { سوپر(نام_کاربری، پسورد، یادآوری_من، میزبان); این.captcha = captcha; این.locale = locale; } }
آخرین یک کلاس اجرایی تأیید است SystemAuthorizationRealm:
پکاج کام چونهوي ويسيرفيس ماودولز سيسي.سيكريتي; استيراد سیریالایزابل جاوا.ایو. استيراد هاشمپا جاوا.یوتیل.هاشمد; استيراد لیست جاوا.یوتیل.لیست; import java.util.Map; import javax.annotation.PostConstruct; import com.chunhui.webservice.common.utils.EmployeeType; import com.chunhui.webservice.common.utils.VertifyStatus; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; استيراد أورج اسبرينج شيرو أوتورايزن كريندينسيال هاشد كرندينسيال ماتشر; استيراد أورج اسبرينج شيرو أوتورايزن أوتورايزن إيفو; استيراد أورج اسبرينج شيرو أوتورايزن سيمبل أوتورايزن إيفو; استيراد أورج اسبرينج شيرو كاش; استيراد أورج اسبرينج شيرو ريلم آوتورايزنغ ريلم; استيراد أورج اسبرينج شيرو سيسيون; استيراد أورج اسبرينج شيرو كوسبكت برينسيبال كوللكشن; استيراد أورج اسبرينج شيرو كوسبكت سابجكت سيمبل ب्रينسيبال كوللكشن; استيراد أورج اسبرينج شيرو كوسبكت سابجكت; استيراد أورج اسبرينج كونتينيوس أنوتييون ديبينز آون; استيراد أورج اسبرينج ستريتيجي سيرفيس; استيراد كوم تشونهوي ويسيرفيس كوم كومن سيرفلتس فيليديتي كود سيرفلتس; استيراد كوم تشونهوي ويسيرفيس كوم كومن يونيتيس.سبرينج كونتائيدير; import com.chunhui.webservice.modules.sys.entity.Employee; import com.chunhui.webservice.modules.sys.entity.Menu; import com.chunhui.webservice.modules.sys.service.SystemService; import com.chunhui.webservice.modules.sys.utils.SystemUtils; import com.chunhui.webservice.modules.sys.web.LoginController; /** * فئة تنفيذ الأمان النظامية*/ @Service @DependsOn({ "employeeDao", "roleDao", "menuDao" }) public class SystemAuthorizingRealm extends AuthorizingRealm { private SystemService systemService; /** * دالة استدعاء التحقق، يتم استدعاؤها عند تسجيل الدخول */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authcToken; // تحقق من الرمز التحقق Session session = SecurityUtils.getSubject().getSession(); // إعداد وقت انتهاء الصلاحية المستقل للجلسة session.setTimeout(60000); String code = (String) session.getAttribute(ValidateCodeServlet.VALIDATE_CODE); إذا (token.getCaptcha() == null || !token.getCaptcha().toUpperCase().equals(code)) { throw new CaptchaException("خطأ في الرمز التحققية!"); } // إذا لم يكن الحساب موجودًا، يتم عرض //throw new UnknownAccountException(); // إذا تم تعطيل الحساب، يتم عرض //throw new DisabledAccountException(); // حفظ اللغة المختارة عند تسجيل الدخول SecurityUtils.getSubject().getSession().setAttribute("locale", token.getLocale()); try{ SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(new Principal(employee), employee.getPassword(), getName()); return info; } t.printStackTrace(); throw new AuthenticationException(); } } * إعادة تعريف وظيفة الاستدعاء للتحقق من الأذونات، يتم استدعاؤها عند عدم وجود معلومات الأذونات للمستخدم في المخزن */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { Principal principal = (Principal) getAvailablePrincipal(principals); Employee employee = getSystemService().getEmployeeByName(principal.getUsername()); إذا (employee != null) { SystemUtils.putCache("employee", employee); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); List<Menu> list = SystemUtils.getMenuList(); لـ (Menu menu : list) { if (StringUtils.isNotBlank(menu.getPermission())) { // إضافة معلومات الصلاحيات بناءً على Permission for (String permission : StringUtils.split(menu.getPermission(), ",")) { info.addStringPermission(permission); } } } // تحديث عنوان IP ووقت الدخول getSystemService().updateEmployeeLoginInfo(employee.getId()); return info; } else { return null; } } /** * إزالة التحقق المترابط مع المستخدم، وإعادة التحميل عند الاستخدام التالي */ public void clearCachedAuthorizationInfo(String principal) { SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName()); clearCachedAuthorizationInfo(principals); } /** * إزالة جميع التحققات المترابطة */ public void clearAllCachedAuthorizationInfo() { Cache<Object, AuthorizationInfo> cache = getAuthorizationCache(); if (cache != null) { for (Object key : cache.keys()) { cache.remove(key); } } } /** * الحصول على موضوع الأعمال النظامية */ public SystemService getSystemService() { if (systemService == null) { systemService = SpringContextHolder.getBean(SystemService.class); } return systemService; } /** * معلومات المستخدم المصرح به */ public static class Principal implements Serializable { private static final long serialVersionUID = 1L; private String id; private String username; private String realname; private Map<String, Object> cacheMap; public Principal(Employee employee) { this.id = employee.getId(); this.username = employee.getUsername(); this.realname = employee.getRealname(); } public String getId() { return id; } public String getUsername() { return username; } public String getRealname() { return realname; } public Map<String, Object> getCacheMap() { if (cacheMap == null) { cacheMap = new HashMap<String, Object>(); } return cacheMap; } } }
ثم يمكن في صفحة JSP الحصول على نوع الاستثناء الخاص بالاستثناء في عملية الدخول لعرض سبب الخطأ
<%String error = (String) request.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);%> <c:set var="exp_type" value="<%=error %>"/> <c:set var="tips" value=""></c:set> <c:if test="${fn:contains(exp_type,'CaptchaException')}"> <c:set var="tips" value="خطأ في رمز التحقق"></c:set> </c:if> <c:if test="${fn:contains(exp_type,'FailVertifyException')}"> <c:set var="tips" value="لم يتم قبول مراجعة حساب هذا، لا يُسمح بالدخول!"></c:set> </c:if> <c:if test="${fn:contains(exp_type,'NotVertifyException')}"> <c:set var="tips" value="حساب هذا يمر بمراجعة، لا يُسمح بالدخول!"></c:set> </c:if> <c:if test="${fn:contains(exp_type,'UnknownAccountException')}"> <c:set var="tips" value="حساب غير موجود!"></c:set> </c:if> <c:if test="${fn:contains(exp_type,'DisabledAccountException')}"> <c:set var="tips" value="حساب غير مسموح بالدخول!"></c:set> </c:if> <c:if test="${fn:contains(exp_type,'IncorrectCredentialsException')}"> <c:set var="tips" value="كلمة المرور غير صحيحة!"></c:set> </c:if>
هذا هو نهاية محتوى هذا المقال، نأمل أن يكون قد ساعد في تعلمكم، ونأمل أن تدعموا دائمًا تعليمات التصرير.
البيان: محتوى هذا المقال تم جمعه من الإنترنت، ملكية حقوق النشر لأصحابها، تم جمعه من قبل المستخدمين على الإنترنت الذين قدموا المساهمات بأنفسهم وأعلى، هذا الموقع لا يمتلك حقوق الملكية، لم يتم تعديل المحتوى بشكل إنساني، ولا يتحمل أي مسؤولية قانونية مرتبطة. إذا اكتشفت محتوى يشتبه في حقوق النسخ، فلا تتردد في إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (عند إرسال البريد الإلكتروني، يرجى استبدال # بـ @) لإبلاغنا، وتقديم الدليل، وستقوم الموقع على الفور بإزالة المحتوى المزعوم.