هناك العديد من الطرق لتنفيذ التحقق من الإذن الوظيفي. أحدهما هو استخدام اعتراض لاعتراض الطلبات ، والآخر هو استخدام AOP لرمي الاستثناءات.
أولاً ، استخدم اعتراضًا لإدراك وظيفة القفز إلى واجهة تسجيل الدخول عند عدم تسجيل الدخول. لاحظ أن AOP لا يتم استخدامه هنا ، ولكن يتم اعتراض التقاطعات ، لأن AOP يدخل عمومًا طريقة طبقة الخدمة ، ويعترض اعتراض الطلب من طبقة وحدة التحكم. إنه أيضًا معالج نفسه ، والذي يمكنه مقاطعة تمرير الطلب مباشرة وإرجاع العرض ، بينما لا يمكن AOP.
1. استخدم التقاطع لتحقيق وظيفة القفز إلى واجهة تسجيل الدخول عند عدم تسجيل الدخول
1.1 Interceptor SecurityInterceptor
package com.jykj.demo.filter ؛ import java.io.printwriter ؛ import javax.servlet.http.htpservletrequest ؛ import javax.servlet.http.httpservletresponse ؛ import javax.servlet.http.http.httpservense ؛ kavax.servlet.http.httpsession ؛ استيراد org.springframework.web.servlet.handlerinterceptor ؛ استيراد org.springframework.web.servlet.modelandview com.jykj.demo.util.result ؛ Public Class SecurityInterceptor تنفذ المعالج {Override public boolean prehandle (httpservletrequest طلب ، استجابة httpservletponse ، معالج الكائن) استثناء { System.out.println ("SecurityInterceptor:"+request.getContextPath ()+"،"+request.getRequesturi ()+"،"+request.getMethod ()) ؛ جلسة httpsession = request.getSession () ؛ if (session.getAttribute (helper.session_user) == null) {system.out.println ("uputizationException: لم يتم تسجيلها في!" +request.getMethod ()) ؛ if ("post" .equalsignoreCase (request.getMethod ())) {reponse.setContentType ("text/html ؛ charset = utf-8") ؛ printWriter out = response.getWriter () ؛ Out.write (json.tojsonstring (نتيجة جديدة (خطأ ، "لم يتم تسجيل الدخول!"))) ؛ out.flush () ؛ out.close () ؛ } else {response.sendRedirect (request.getContextPath ()+"/login") ؛ } إرجاع خطأ ؛ } آخر {return true ؛ }}} Override public void posthandle (httpservletrequest request ، httpservletresponse ، معالج الكائنات ، modelandview modelandview) يلقي الاستثناء {// todo method method method exponstride exponster exponster exponster exponster exponster expontride TODO Method Method Method}}}1.2.SPRING-MVC.XML (جزء تكوين التقاطع)
<!-مقابض http احصل على طلبات/موارد/** عن طريق خدمة الموارد الثابتة بكفاءة في دليل $ {webapproot}-> <mvc: mapping = "/الموارد/**" الموقع = "/الموارد/"/> <mvc: interceptors> <mvc: interceptor> مثل/اختبار/تسجيل الدخول-> <mvc: mapping path = "/**/*. <mvc: استبعاد path = "/register"/> <bean> </bean> </mvc: interceptor> </mvc: interceptors>من الضروري تحديد هنا: يفضل أن يكون المسار الذي تم اعتراضه بواسطة المعترض مع اسم لاحقة ، وإلا سيكون من الصعب التحكم في بعض ملفات الموارد الثابتة ، أي أن الطلب يجب أن يكون له تنسيق موحد مثل .do ، وما إلى ذلك ، بحيث تكون سرعة المطابقة والتصفية سريعة للغاية. إذا لم يكن هذا هو الحال ، على سبيل المثال باستخدام /** لاعتراض جميع الطلبات ، ستكون سرعة عرض الصفحة بطيئة للغاية لأن ملف المورد يتم اعتراضه أيضًا.
2. استخدم AOP لتنفيذ التحقق من الإذن الوظيفي
يمكن أيضًا تنفيذ التحقق من إذن الوظيفة بشكل مشابه مع اعتراض ، ولكنه سيعترض جميع الطلبات وليس لديه وظيفة تصفية جيدة للطلبات التي لا تتطلب التحقق من الإذن. لذلك ، يتم تنفيذها باستخدام AOP لتحديد طريقة اعتراض التحقق المطلوب.
2.1 الإذن
package com.jykj.demo.filter ؛ import java.io.ioException ؛ import java.lang.reflect.method ؛ import org.aspectj.lang.joinpoint ؛ import org.asprice.lang.reflect.methodsignature ؛ com.jykj.demo.annotation.validatePermission ؛ استيراد com.jykj.demo.exception.accessdeniedException ؛ استيراد com.jykj.demo.service.sysuserrolepermservice ؛/*** قسم سجل الأحداث ، أي وحدة تحكم مع ValidatePermission و Responsebodybodybody. * إذا لم يكن هناك إذن ، يتم إلقاء استثناء من AccessDeniException ، والذي يقوم بإعادة توجيه الطلب إلى وحدة تحكم ، ثم يعيد نتيجة الاستثناء * Administor * */Public Class PrecissionAspect {autowired sysuserrolepermservice sysuserrolepermservice ؛ public void debefore (JoinPoint jp) يلقي ioException {system.out.println ("log percissionaspect قبل الطريقة:" + jp.getTarget (). getClass (). getName () + ". طريقة آسف Method = getSourCemethod (JP) ؛ if (soruceMethod! = null) {validatePermission Opera = sorresmethod.getAnnotation (validatePermission.class) ؛ if (oper! = null) {int fidx = opera.idx () ؛ Object [] args = jp.getargs () ؛ if (fidx> = 0 && fidx <args.length) {int functionId = (integer) args [fidx] ؛ سلسلة rs = sysuserRolePermService.permissionValidate (functionId) ؛ System.out.println ("SERMISSORVALIDADED:"+rs) ؛ if (rs.trim (). isEmpty ()) {return ؛ // normal}}}} رمي AccessDeniedException ("ليس لديك إذن للعمل!") ؛ } الطريقة الخاصة getSourCemethod (JoinPoint jp) {method proxymethod = ((MaysIngureature) jp.getSignature ()). getMethod () ؛ حاول {return jp.getTarget (). getClass (). getMethod (proxymethod.getName () ، proxymethod.getParameterTypes ()) ؛ } catch (nosuchmethodexception e) {e.printStackTrace () ؛ } catch (SecurityException e) {E.PrintStackTrace () ؛ } إرجاع فارغ ؛ }}2.2 التعليق التوضيحي المخصص
package com.jykj.demo.annotation ؛ import java.lang.annotation.documented ؛ import java.lang.annotation.elementtype ؛ import توضيح TAG-TYPE. تتطلب الطريقة المشروطة بواسطة هذا التعليق التوضيحي التحقق من الإذن* /@@target (value = elementType.method) receation (value = entrentionpolicy.runtime) documentedpublic@interface validatepermiss */ int idx () افتراضي 0 ؛}
ملاحظة: يقوم AOP بتقطيع طريقة ، وليس طلبًا من وحدة تحكم ، لذلك لا يمكن العودة مباشرة إلى العرض لمقاطعة طلب الطريقة ، ولكن يمكن تحقيق الغرض من مقاطعة تنفيذ الطريقة من خلال إلقاء الاستثناءات. لذلك ، في الإخطار السابق ، إذا قمت بإرجاع طريقة نقطة الاتصال مباشرةً من خلال التحقق ، وإلا فسيتم إلقاء AccessedException الاستثناء المخصص لمقاطعة تنفيذ طريقة نقطة الاتصال. يمكن التقاط التقاط الاستثناء وإعادة توجيهه إلى عرض أو طلب من خلال معالج استثناء النظام (يمكن اعتباره وحدة تحكم). هذا يحقق الغرض من اعتراض الطلب. لذلك ، يجب تكوين معالج الاستثناء.
2.3 Spring-MVC.XML (تكوين معالج الاستثناء ، وتكوين AOP)
<Bean> <!-<property name = "defaulterrorview" value = "rediRet:/error"> </spleneration>-> <property name = "inspeciedMappings"> <bors> <!-<prop key = "com.jykj.demo.exception.authorization key = "com.jykj.demo.exception.accessdeniedException"> إلى الأمام:/AccessDenied </props> </props> </property> </bole> <bean id = "sideperpermission"/> <!-تنفيذ الإذن بالدالة على جميع طرق حزمة وحدة التحكم و subpackageate مع ValidateMisming- <aOP: Side ref = "SidePermission"> <aop: pointcut id = "pc" expression = " @enoTation (com.jykj.demo.annotation.validatePermission) و annotation (org.springframework.web.bind.annotation.responsebody) و execution (*com.jykj.demo <aop: قبل pointcut-ref = "pc" method = "debefore"/> </aop: side> </ aop: config>
2.4 شرح طلبات وحدة التحكم التي تتطلب التحقق الوظيفي
requestmapping (value = "/moduleAccess.do" ، method = requestMethod.post ، produces = "text/html ؛ charset = utf-8") responsebodyvalidatepermission public moduleaccess (int fid ، string action ، module) {system.pintln ( int rs = -1 ؛ حاول {if (helper.f_action_create.equals (action)) {rs = moduleservice.access (الوحدة النمطية ، helper.db_action_insert) ؛ //module.setModuleId(RS) ؛ الوحدة = moduleservice.selectbyprimarykey (rs) ؛ } آخر إذا (helper.f_action_edit.equals (Action)) {rs = moduleservice.access (الوحدة النمطية ، helper.db_action_update) ؛ الوحدة النمطية = moduleservice.selectbyprimarykey (module.getModuleId ()) ؛ } آخر إذا (helper.f_action_remove.equals (Action)) {rs = moduleservice.access (الوحدة النمطية ، helper.db_action_delete) ؛ } آخر {return json.tojsonstring (نتيجة جديدة (خطأ ، "خطأ في المعلمة: الإجراء")) ؛ }} catch (استثناء e) {E.PrintStackTrace () ؛ return json.tojsonstring (نتيجة جديدة (خاطئة ، "فشل العملية ، حدث استثناء ، يرجى الاتصال بالمسؤول!")) ؛ } if (rs <0) {return json.tojsonstring (نتيجة جديدة (خطأ ، "فشلت العملية ، يرجى الاتصال بالمسؤول!")) ؛ } return json.tojsonstring (نتيجة جديدة (صواب ، وحدة)) ؛ }2.5 طلب وحدة التحكم إلى الأمام:/Accessdenied بواسطة معالج الاستثناء إلى الأمام:/Accessdenied
requestmapping (value = "/accessdenied" ، تنتج = "text/html ؛ charset = utf-8")@responsebodypublic string accessdenied () {return json.tojsonstring (نتيجة جديدة (خطأ ، "أنت لا تملك إذنًا للعمل على هذا!)) ؛}2.6 عند فشل التحقق من الطلب ، تقوم وحدة التحكم أعلاه بإرجاع النتيجة نفسها.
كما هو موضح أدناه:
{"معلومات": "ليس لديك إذن للعمل على هذا!" ، "النجاح": false}
2.7 مثال خدمة التحقق من الوظائف
/ *** تحقق من إذن المستخدم الحالي في دالة معينة من وحدة نمطية* param functionId* return تشير سلسلة فارغة إلى الإذن ، وإلا فهي رسالة خطأ* @Throws*/ السلسلة العامة إذن (int functionId) {object o = request.getSession (). // if (o == null) رمي التفويض الجديد () ؛ sysuser loginuser = (sysuser) o ؛ if (logInUser.getuserId () == 1) return "" ؛ حاول {return mapper.permissionValidate (loginUser.getuserId () ، functionId) ؛ } catch (استثناء ex) {ex.printStackTrace () ؛ عودة "استثناء حدث في عملية قاعدة البيانات!" ؛ }} ملاحظة: نحن هنا فقط نقطع جميع طرق حزمة وحدة التحكم وحقائبها الفرعية مع ValidatePermission و @ResponseBody التعليقات التوضيحية. هذا بالتأكيد ليس عالمي بما فيه الكفاية. يجب أن نقطع الطريقة مع ValidatePermission. في فئة القسم ، سنقوم بإلقاء استثناءات مختلفة عن طريق الحكم على ما إذا كانت الطريقة لديها تعليقات @ResponseBody. إذا تم طرح الاستثناء أعلاه ، يتم إلقاء الاستثناء أعلاه وإعادته إلى سلسلة JSON.
خلاف ذلك ، يجب إلقاء استثناء مخصص آخر وإعادة توجيه الطلب إلى وجهة نظر قانونية مثل error.jsp.
Send /ModuleAccess.do طلب من خلال العميل. تحتوي الطريقة المقابلة للطلب على كل من ValidatePermission و @ResponseBody ، ولها معلمة معرف الوظيفة FID ، بحيث يمكن لـ AOP إدخال الطريقة ، وتنفيذ إشعار Debefore ، واستخدام معلمة Function Fid للتحقق من أذوناتها مع معرف المستخدم. إذا تم تمرير التحقق ، فسيستمر البرنامج في تنفيذه. خلاف ذلك ، يتم إلقاء استثناء مخصص AccessDeniedException. يتم اكتشاف الاستثناء من قبل النظام (يجب تكوين معالج الاستثناء) ويتم إصدار طلب للأمام:/AccessDenied ، ويتعامل وحدة التحكم/Accessdenied المقابلة مع الطلب وإرجاع JSON الذي يحتوي على معلومات فشل التحقق إلى العميل. هذا يرسل طلب /moduleccess.do. إذا فشل التحقق ، قم بإعادة توجيه طلب /Accessdenied ، وإلا فإنه سيتم تنفيذه بشكل طبيعي. تم تحقيقه بعد الالتفاف على هذه الدائرة الكبيرة.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.