شيرو
شيرو هو مشروع مفتوح المصدر تحت Apache ، نسميه Apache Shiro. إنه إطار أمان سهل الاستخدام للغاية مع مشاريع Java ، حيث يوفر المصادقة ، والترخيص ، والتشفير ، وإدارة الجلسة. مثل أمن الربيع ، إنه إطار أمان للإذن. ومع ذلك ، بالمقارنة مع SPRING Security ، يستخدم Shiro طريقة ترخيص بسيطة نسبيًا وسهلة الفهم وسهلة الاستخدام. شيرو هو إطار خفيف الوزن. إنه أبسط بكثير من الأمن وليس معقدًا مثل الأمن. لمزيد من التقديمات التفصيلية ، يمكنك التعلم بشكل أساسي من موقعها الرسمي (http://shiro.apache.org/) الذي يوفر الوظائف التالية بشكل أساسي:
(1) المصادقة (المصادقة)
(2) إذن (إذن)
(3) إدارة الجلسة (إدارة الجلسة)
(4) التشفير (التشفير)
بادئ ذي بدء ، فإن خدمة المصادقة ، أي من خلالها ، يمكنك إكمال مصادقة الهوية ، مما يسمح لها بتحديد ما إذا كان المستخدم عضوًا حقيقيًا.
ثانياً ، الخدمة المعتمدة ، لوضعها بصراحة ، هي خدمة "التحكم في الوصول" ، أي دعها تحدد الأذونات التي يتمتع بها المستخدم. بعبارة صريحة ، فإن منحه أذونات العملية من خلال الحكم على الدور الذي يكون عليه المستخدم.
ثم ، هناك خدمة إدارة الجلسة. في هذا الوقت ، يختلف إطار عمل إدارة الجلسة المستقل عن جلسة HTTP التي نعرفها.
أخيرًا ، توفر أيضًا خدمات التشفير (التشفير) ، وتغلف العديد من خوارزميات التشفير.
اليوم ، لن أقول كل شيء عن ذلك ، وأركز على وظيفة إدارة المحادثة. في الواقع ، هذا شيء يجب أن تشارك جميع الشبكات تقريبًا.
قبل الحديث عن خدمة إدارة جلسة شيرو ، دعنا نراجع كيف قمنا بإدارة الجلسة السابقة.
1. في البداية استخدمنا مباشرة آلية جلسة HTTP لخادم الويب. هذا هو ، إذا جاء المستخدم لأول مرة ، فستقوم حاوية الويب بإنشاء جلسة للطلب ، ثم تخزين الجلسة. من خلال تمرير SessionId المقابل كملف تعريف ارتباط للعميل.
إذا أرسل العميل طلبًا إلى هذا الخادم مرة أخرى ، فسيتم إحضار SessionId تلقائيًا. بعد ذلك ، سيحدد خادم الويب ما إذا كانت الجلسة لا تزال في الذاكرة بناءً على SessionId الذي جلبه العميل (الجلسة لديها وقت انتهاء صلاحية ويمكن تكوينها في ملف web.xml). إذا تعذر العثور على الجلسة المقابلة ، فهذا يعني أن وقت انتهاء صلاحية الجلسة قد مرت. في هذا الوقت ، سيقوم خادم الويب بإنشاء جلسة لها مرة أخرى ، ثم تمرير SessionId الجديد إلى العميل كما كان من قبل.
لذلك ، يمكننا استخدام هذه الآلية لإدارة جلسة تسجيل الدخول الخاصة بالمستخدم في البرنامج. على سبيل المثال ، بعد نجاح تسجيل الدخول الأول للمستخدم ، نقوم بتخزين المعلومات الأساسية للمستخدم في الجلسة (على سبيل المثال: session.setAttribute("user", "userInfo") ). في المرة التالية التي يزور فيها المستخدم مرة أخرى ، نحصل على معلومات المستخدم في الجلسة الحالية بناءً على معلومات المستخدم
( session.getAttribute("user") ) لتحديد ما إذا كان المستخدم قد انتهى. إذا كان لا يمكن الحصول عليها ، فسيتم مطالب المستخدم بتسجيل الدخول مرة أخرى.
2. الطريقة الثانية هي نقل المكان الذي يتم فيه تخزين المعلومات إلى وسائط الطرف الثالث ، مثل ذاكرة التخزين المؤقت أو Memecache أو Redis. يتم اعتماد هذه الطريقة بشكل أساسي بسبب ظهور الأنظمة الموزعة.
في هذه الحالة ، نحتاج إلى توليد SessionId بأنفسنا. بشكل عام ، سوف نستخدم بادئة محددة ( user:login:token ) وإضافة userId أو الطابع الزمني. بعد ذلك ، سنستخدم هذا SessionId كمفتاح ذاكرة التخزين المؤقت ، ومعلومات المستخدم كقيمة ، وتخزينها في ذاكرة التخزين المؤقت ، وتعيين وقت الإبطال:
jedisclient.set (tokenkey ، jsonutil.tojsonstring (userInfo)) ؛ jedisclient.expire (tokenkey ، token_lose_seconds) ؛
نحتاج أيضًا إلى تمرير الرمز المميز الذي تم إنشاؤه إلى العميل من خلال ملفات تعريف الارتباط: CookieUtils.setCookie(request, response, "TT_TOKEN", tokenKey);
وبهذه الطريقة ، عندما يزور المستخدم في المرة التالية (يحدد اعتراض) ، يمكننا إخراج الرمز المميز المقابل من ملف تعريف الارتباط ، ثم استخدم هذا الرمز المميز للذهاب إلى ذاكرة التخزين المؤقت لاسترداد القيمة المقابلة. إذا كان لا يمكن الحصول عليها ، فهذا يعني أن المفتاح قد انتهى ويتم مطالب المستخدم بتسجيل الدخول مرة أخرى.
ملاحظة: Tokenkey مهم ، إنه المحور الذي يربط جانب ذاكرة التخزين المؤقت والعميل.
3. آخر طريقة هي طريقة شيرو لدينا ، والفكرة متشابهة. الرمز بسيط للغاية ، لذلك سأقوم فقط بتحميل الرمز:
1) إنشاء ملف ApplicationContext-shiro.xml جديد:
<؟ xmlns: p = "http://www.springframework.org/schema/p" XSI: schemalocation = "http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframeworg http://www.springframework.org/schema/Aop http://www.springframework.org/schema/tx/spring-tx-4.0.xsd id = "shirofilter"> <property name = "securitymanager" ref = "securityManager"> </sprement> <property name = "loginurl" value = "/logInPage"> </property> <property name = "unauthorizedurl /logout = anon </value> </sopperation> </bean> <bean> <property name = "staticmethod" value = "org.apache.shiro.securityUtils.SetSecurityManager"> </property> <splants name = "edation" ref = "securitymanager"> </propert ref = "cachemanager"> </sopperation> <property name = "SessionManager" ref = "sessionManager"> </property> </bean> <bean id = "sessionmanager"> <property name = "sessiondao" ref = "sessiondao
2) تكوين المرشح المقابل في web.xml:
<Ivilter> <ilter-name> shirofilter </filter-name> <ilter-class> org.springframework.web.filter.delegatingfilterproxy </filter-class> <Ing-param> <param-name> targetFilterLifecycle </param-name> <filter-mapping> <filter-name> shirofilter </filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
3) اكتب فئة التنفيذ ، وراثي الملخصات ، وتنفيذ الطريقة المقابلة.
package com.jdd.core.shiro ؛ import com.smart.core.redis.redismanager ؛ import org.apache.shiro.session.session ؛ import org.apache.shiro.session.unknownsessionexception ؛ import org.apache.shiro.session.mgt.iis.abstracteddao ؛ org.springframework.beans.factory.annotation. تحديث Override public void (جلسة الجلسة) يلقي unknownsessionException {redismanager.set (serializationUtils.Serialize (Session.getId (). redismanager.expire (serializationUtils.serialize (session.getId (). toString ()) ، 60) ؛ } Override public void delete (جلسة الجلسة) {redismanager.del (serializationUtils.serialize (session.getId (). toString ())) ؛ } Override Public Collection <Session> getActiptessions () {return new ArrayList <Session> () ؛ } override محمية متسلسلة (جلسة جلسة) {// هذا هو عندما يمكنك الوصول أولاً ، إنشاء SessionId Serializable Sid = this.generatesessionId (الجلسة) ؛ EnvisionSessionId (جلسة ، SID) ؛ redismanager.set (serializationUtils.Serialize (session.getID (). redismanager.expire (serializationUtils.serialize (session.getId (). toString ()) ، 60) ؛ إرجاع سيد. } Override Session Doreadsession (serializableableable) {// هذه الطريقة هي في الواقع قراءة الجلسة من خلال SessionId. في كل مرة تقرأها ، يجب إعادة تعيين وقت الفشل [] aa = redismanager.get (serializationutils.serialize (serializable.toString ())) ؛ جلسة الجلسة = (الجلسة) SerializationUtils.Deserialize (AA) ؛ redismanager.set (serializationutils.serialize (serializable.toString ()) ، serializationutils.serialize (الجلسة)) ؛ redismanager.expire (serializationUtils.Serialize (serializable.toString ()) ، 60) ؛ جلسة العودة ؛ }}4) الخطوة التالية هي الحصول على جلسة Shiro في المنطق بعد تسجيل الدخول الناجح ، ثم تعيين معلومات المستخدم في
package com.smart.controller ؛ استيراد com.smart.pojo.user ؛ استيراد com.smart.service.userservice ؛ import org.apache.shiro org.slf4j.loggerfactory ؛ استيراد org.springframework.beans.factory.Antation.autowired ؛ استيراد org.springframework.steretype.controller ؛ استيراد org.springframework.ui.model ؛ javax.servlet.http.httpservletrequest ؛ استيراد javax.servlet.http.httpservletresponse ؛@controller@requestMapping ("/user") الفئة العامة USERCONTROLLER Autowired Private SecurityManager SM ؛ // حقن SecurityManager Logger Logger = loggerFactory.getLogger (UserController.class) ؛ requestMapping (value = "/logInPage") public string loginPage () {return "user/userLogin" ؛ } @requestmapping (value = "/userlogin" ، method = requestMethod.post) السلسلة العامة userLogin ( @requestparam (value = "name") اسم السلسلة ، requestparam (value = "pwd") السلسلة pwd ، نموذج النموذج) {logger.info ("أدخل userlogin ...") ؛ مستخدم المستخدم = userservice.getuserBynameAndPassword (الاسم ، PWD) ؛ if (user == null) {logger.info ("المستخدم غير موجود ...") ؛ model.addattribute ("login_error" ، "اسم المستخدم أو خطأ كلمة المرور") ؛ إرجاع "المستخدم/userlogin" ؛ } SecurityUtils.SetSecurityManager (SM) ؛ موضوع currentUser = securityUtils.getSubject () ؛ CurrentUser.getSession (). setAttribute ("login_user" ، user) ؛ إرجاع "إعادة التوجيه:/موظف/قائمة" ؛ }}احصل على المستخدم الحالي ، في Shiro ، إنه السمة ، ثم احصل على الجلسة المقابلة ، وقم بتعيين معلومات المستخدم فيه. هل تشعر أنها تشبه إلى حد ما تشغيل جلسة HTTP؟ هاها.
5) أخيرًا ، حدد اعتراض SPRINGMVC للحصول على معلومات المستخدم في الجلسة المقابلة في التقاطع. إذا كان لا يمكن الحصول عليها ، فسيقفز إلى واجهة تسجيل الدخول.
package com.smart.core.shiro ؛ استيراد com.smart.pojo.user ؛ import org.apache.shiro.securityutils ؛ import org.apache.shiro org.slf4j.loggerfactory ؛ استيراد org.springframework.beans.factory.annotation. javax.servlet.http.httpservletrequest ؛ import javax.servlet.http.httpservletresponse ؛ public class loginInterceptor تنفذ HandlerInterceptor {private logger logger = loggerfactory.getlogger (logininterceptor.class) ؛ Autowired Private SecurityManager SM ؛ Override public boolean prehandle (httpservletrequest httpservletrequest ، httpservletresponse httpservletresponse ، كائن O) يلقي الاستثناء {logger.info ( httpservletrequest طلب = httpservletrequest ؛ httpservletresponse استجابة = httpservletResponse ؛ logger.info ("request uri ===>"+request.getRequesturi ()) ؛ // إذا كان طلبًا لصفحة تسجيل الدخول ، فلن يتم اعتراضه ، وإلا فإنه سيقع في حلقة ميتة إذا كان (request.getRequesturi (). يحتوي على ("loginPage") || request.getRequesturi (). يحتوي على ("userlogin")) {return true ؛ } آخر {SecurityUtils.SetSecurityManager (SM) ؛ موضوع currentUser = securityUtils.getSubject () ؛ Object obj = currentUser.getSession (). getAttribute ("login_user") ؛ if (obj == null) {response.sendRedirect ("http: // localhost: 8080/user/loginPage") ؛ العودة كاذبة } آخر {user user = (user) obj ؛ if (user == null || user.getName () == null) {response.sendRedirect ("http: // localhost: 8080/user/loginPage") ؛ العودة كاذبة } آخر {return true ؛ }}}} @Override pubthandle posthandle (httpservletrequest httpservletrequest ، httpservletresponse httpservletrespons httpservletresponse ، كائن O ، استثناء E) يلقي الاستثناء {}}إنه أساسا هنا. إذا قمت بالوصول إلى معلومات الصفحة الرئيسية مباشرة الآن ، فسوف تقفز تلقائيًا إلى صفحة تسجيل الدخول.
لخص
ما سبق هو المحتوى الكامل لهذه المقالة. آمل أن يكون لمحتوى هذه المقالة قيمة مرجعية معينة لدراسة أو عمل الجميع. إذا كان لديك أي أسئلة ، فيمكنك ترك رسالة للتواصل. شكرا لك على دعمك إلى wulin.com.