문제

나는 상대적으로 새롭다 봄 프레임 워크 그리고 봄 보안.

사용자 정의 인증 체계, 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 ?
    }
}
도움이 되었습니까?

해결책

사용자 이름과 비밀번호를 조작하기 위해 추가 양식 매개 변수를 사용해야하는 경우 자체 인증 프로세싱 필터를 구현할 수 있습니다.

http://static.springsource.org/spring-security/site/apidocs/org/springframework/security/ui/webapp/authenticationprocessingfilter.html

이 클래스는 httprequest에 완전히 액세스 할 수 있으며, 따라서 제출 한 모든 추가 매개 변수가 있습니다. 목표가 어떻게 든 이러한 값을 사용하여 사용자 이름과 비밀번호를 수정하는 것이라면, 이것이 당신이 할 수있는 곳입니다.

다른 팁

위의 모든 것은 훌륭하고 완벽한 솔루션입니다. 그러나 나는 완벽하게 잘 작동하는 해결 방법을 사용했습니다. ThreadLocal에 Multitenant ID를 사용했습니다

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 {

    }
}

스프링 보안 XML

<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();

그런 다음 요청 객체를 사용하여 사용자 정의 매개 변수를 얻습니다.

여기서 비결은 usernameandpasswordauthenicationtoken을 확장하는 새로운 AuthenicationToken (아마도)을 만들어야한다는 것입니다. @emills가 말했듯이 새로운 AuthenciationProcessingFilter를 구현하여 요청 값을 토큰에 매핑하고 인증 관리자에게 제출해야합니다.

기본적으로 스프링 보안에서 사용자 정의 인증 체인을 구현하는 데 몇 가지 부분이 있습니다.

  • AuthenicationToken - 인증 요청의 세부 사항 및 결과, 즉 인증하는 데 필요한 자격 증명이 포함되어 있습니다.
  • AuthenicationProvider - AuthenicationManager에 등록하고 AuthenicationToken을 수락하고 사용자를 확인하고 부여 된 당국 세트와 함께 토큰을 반환합니다.
  • AuthenciationFilter - 실제로 추상 프로세싱 필터를 사용하는 것만으로 필터 일 필요는 없습니다.

나는 이런 식으로 갈 것이다 :

<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