هل من الممكن إرسال المزيد من البيانات في المصادقة المستندة إلى النموذج في الربيع؟

StackOverflow https://stackoverflow.com/questions/1629273

سؤال

أنا جديد نسبيا على إطار الربيع وأمن الربيع.

لقد استخدمت نظام مصادقة مخصص، HTML:

<form action="j_spring_security_check">
    <input type="text" name="j_username" value="abc"/>
    <input type="text" name="j_password" value="abc"/>
    <input type="text" name="myCustom1" value="pqr"/> <!-- maybe type="hidden" -->
    <input type="text" name="myCustom2" value="pqr"/> <!-- maybe type="hidden" -->
</form>

والكود المقابل:

public class CustomAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider
{
    @Override protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken)
    throws AuthenticationException
    {
        System.out.println("Method invoked : additionalAuthenticationChecks isAuthenticated ? :"+usernamePasswordAuthenticationToken.isAuthenticated());
    }

    @Override protected UserDetails retrieveUser(String username,UsernamePasswordAuthenticationToken authentication)
    throws AuthenticationException
    {
        System.out.println("Method invoked : retrieveUser");
        //I have Username,password:
        //HOW CAN I ACCESS "myCustom1", "myCustom2" here ?
    }
}
هل كانت مفيدة؟

المحلول

إذا كنت بحاجة إلى استخدام معلمات النموذج إضافية من أجل التلاعب اسم المستخدم وكلمة المرور، يمكنك تنفيذ AuthenticationProcessingFilter بنفسك

HTTP: / /static.springsource.org/spring-security/site/apidocs/org/springframework/security/ui/webapp/AuthenticationProcessingFilter.html

وهذه الفئة سيكون لها حق الوصول الكامل إلى HttpRequest وبالتالي جميع المعلمات الإضافية التي تقدمها. إذا كان هدفك هو استخدام هذه القيم بطريقة أو بأخرى لتعديل اسم المستخدم وكلمة المرور، وهذا هو المكان الذي سوف نفعل ذلك.

نصائح أخرى

وكلها فوق حلول كبيرة ومثالية. ولكن لقد استخدمت نوع الحل البديل للحل الذي يعمل بشكل جيد تماما. معرف multitenant مستعملة للThreadLocal

package com.mypackage.servlet;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.springframework.util.Assert;

public class ThreadLocalContextUtil implements Filter{
     private static final ThreadLocal<Object> contextHolder =
                new ThreadLocal<Object>();

       public static void setTenantId(Object tenantId) {
          Assert.notNull(tenantId, "customerType cannot be null");
          contextHolder.set(tenantId);
       }

       public static Object getTenantId() {
          return contextHolder.get();
       }

       public static void clearTenant() {
          contextHolder.remove();
       }

    public void destroy() {

    }

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
        // Set the tenant Id into a ThreadLocal object
        ThreadLocalContextUtil.setTenantId(request);
        if(chain != null)
            chain.doFilter(request, response);
        else {
            //error
        }
    }

    public void init(FilterConfig filterconfig) throws ServletException {

    }
}

<القوي> الربيع أكس الأمان     

<security:http auto-config="true" use-expressions="true" access-denied-page="/forms/auth/403" >
    <security:custom-filter before="FIRST" ref="tenantFilter" />
    ......
    </security:http>

وصول وجوه الطلب في الدرجة مصادقة بك

HttpServletRequest currRequest = (HttpServletRequest) ThreadLocalContextUtil.getTenantId();

وثم استخدام الكائن طلب للحصول على المعلمات المخصصة

الحيلة هنا هي أنك تحتاج إلى إنشاء AuthenciationToken جديد (ربما) لتوسيع UsernameAndPasswordAuthenicationToken وكما يقول @emills فإنك تحتاج بعد ذلك إلى تنفيذ AuthenciationProcessingFilter جديد لتعيين قيم الطلب إلى الرمز المميز وإرسالها إلى AuthenciationManager.

يوجد في الأساس جزءان لتنفيذ سلسلة مصادقة مخصصة في أمان الربيع

  • AuthenicationToken - تفاصيل طلب المصادقة ونتيجته، أي أنه يحتوي على بيانات الاعتماد التي تحتاجها للمصادقة
  • AuthenicationProvider - مسجل لدى AuthenicationManager، ويقبل AuthenicationToken الخاص بك ويتحقق من صحة المستخدم ويعيد رمزًا مميزًا مع مجموعة السلطات الممنوحة
  • AuthenciationFilter - ليس من الضروري في الواقع أن يكون مرشحًا، فقط استخدام AbstractProcessingFilter سيجعل حياتك أسهل قليلاً

وأود أن السير في هذا الطريق:

<bean id="authenticationProcessingFilter"  
    class="org.acegisecurity.ui.webapp.AuthenticationProcessingFilter">
  ...
  <property name="authenticationDetailsSource">
    <bean class="org.acegisecurity.ui.AuthenticationDetailsSourceImpl">
        <property name="clazz"  
           value="com.MyAuthenticationDetails"/>
    </bean>
  </property>
</bean>  

وهذه هي الطبقة التي تحمل خصائص:

package com;
import javax.servlet.http.HttpServletRequest;
import org.acegisecurity.ui.WebAuthenticationDetails;
public class MyAuthenticationDetails extends WebAuthenticationDetails {
    public MyAuthenticationDetails() {
      super();
    }
    //This constructor will be invoqued by the filter
    public MyAuthenticationDetails(HttpServletRequest request) {
        super(request);
        this.myCustom1 = request.getParameter("myCustom1");
    }
    public String getMyCustom1() {
        return myCustom1;
    }
    private String myCustom1;
}

والآن لديك اسم المستخدم، كلمة المرور و التفاصيل.

ولقد فعلت شيئا مماثلا، ولكنها مختلفة ثم أي شخص قد اقترح هنا. أنا لا أقول هذا "الحق" وسيلة لتحقيق ذلك - ولكن انها عملت بشكل جيد للغاية بالنسبة لي. في الكائن الرئيسي هناك هو المستخدم وهناك أيضا تفاصيل الكائن في AuthenticationToken التي يمكنك تخزين الخريطة (سلسلة، سلسلة) من معلومات دخولك أخرى.

public class RequestFormDeatils extends SpringSecurityFilter {

   protected void doFilterHttp(HttpServletRequest request, ...) {
      SecurityContext sec = SecurityContextHolder.getContent();
      AbstractAuthenticationToken auth = (AbstractAuthenticationToken)sec.getAuthentication();
      Map<String, String> m = new HashMap<String, String>;
      m.put("myCustom1", request.getParamtere("myCustom1"));
      m.put("myCustom2", request.getParameter("myCustom2"));
      auth.setDetails(m);
}

والآن في أي مكان في التعليمات البرمجية تحصل استخدام SecurityContext لنشر هذه المعلومات المتعلقة بالأمن دون الحاجة لزوجين لUserDetails بك الاعتراض، أو تمريرها كوسائط. أفعل هذا الرمز في SecurityFilter في نهاية سلسلة تصفية الأمن الربيع.

<bean id="requestFormFilter" class="...RequestFormDetails">
   <custom-filter position="LAST" />
</bean> 
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top