2013-06-15 8 views
5

के माध्यम से स्प्रिंग सुरक्षा प्रमाणीकरण मेरे पास एक एपीआई वाला सर्वर है। सर्वर वसंत सुरक्षा द्वारा संरक्षित है।टोकन

मैं एक बाहरी अनुप्रयोगों अनुरोध में टोकन का उपयोग करने से एपीआई के लिए एक एक्सेस प्राप्त करना चाहते पैरामीटर

सबसे पहले उपयोगकर्ता एक सेवा है जो उसे एक टोकन देता है के लिए जाना और फिर इस टोकन के माध्यम से एपीआई का उपयोग करेंगे।

लेकिन मैं मानक वसंत सुरक्षा समाधान के माध्यम से एपीआई की पिछली पहुंच को संरक्षित करना चाहता हूं।

तो, क्या आप कृपया मेरी मदद कर सकते हैं, मैं इसे कैसे कार्यान्वित कर सकता हूं?

+0

OAuth समर्थन की जांच करें। –

उत्तर

7

आप वसंत config

<?xml version="1.0" encoding="UTF-8"?> 
<b:beans 
    xmlns="http://www.springframework.org/schema/security" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:b="http://www.springframework.org/schema/beans" 
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:sec="http://www.springframework.org/schema/security" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd 
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd 
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd 
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd"> 

    <context:annotation-config/> 
    <context:component-scan base-package="com.your.path" /> 

    <aop:aspectj-autoproxy/> 

    <global-method-security pre-post-annotations="enabled" secured-annotations="enabled" proxy-target-class="true" 
          access-decision-manager-ref="accessDecisionManager"/> 

    <http entry-point-ref="restAuthenticationEntryPoint" use-expressions="true" 
     auto-config="true" access-decision-manager-ref="accessDecisionManager"> 
    <custom-filter ref="restFilter" position="PRE_AUTH_FILTER"/> 
    <logout/> 
    </http> 

    <b:bean id="restAuthenticationEntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"/> 

    <b:bean id="restFilter" class="com.your.path.CustomAuthenticationFilter"> 
    <b:property name="authenticationSuccessHandler" ref="mySuccessHandler"/> 
    </b:bean> 

    <b:bean id="mySuccessHandler" class="com.your.path.CustomAuthenticationSuccessHandler"/> 

    <b:bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"> 
    <b:property name="allowIfAllAbstainDecisions" value="true"/> 
    <b:property name="decisionVoters"> 
     <b:list> 
     <b:bean class="org.springframework.security.access.vote.RoleVoter"> 
      <b:property name="rolePrefix" value=""/> 
     </b:bean> 
     <b:bean class="org.springframework.security.access.vote.AuthenticatedVoter" /> 
     </b:list> 
    </b:property> 
    </b:bean> 

</b:beans> 

इस मदद करनी चाहिए में इस

public class CustomAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { 

    @Override 
    protected String determineTargetUrl(HttpServletRequest request, HttpServletResponse response) { 
    return request.getServletPath(); 
    } 

    @Override 
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException { 
    request.getRequestDispatcher(request.getServletPath()).forward(request, response); 
    } 
} 

की तरह इस

public class CustomAuthenticationFilter extends AbstractAuthenticationProcessingFilter { 

    private static final String SECURITY_TOKEN_KEY = "token"; 
    private static final String SECURITY_TOKEN_HEADER = "X-Token"; 
    private String token = null; 

    protected CustomAuthenticationFilter() { 
    super("/"); 
    } 

    @Override 
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 
    HttpServletRequest request = (HttpServletRequest) req; 
    HttpServletResponse response = (HttpServletResponse) res; 

    this.token = request.getParameter(SECURITY_TOKEN_KEY); 
    // or this.token = request.getHeader(SECURITY_TOKEN_HEADER); 

    if (request.getAttribute(FILTER_APPLIED) != null) { 
     chain.doFilter(request, response); 
     return; 
    } 

    request.setAttribute(FILTER_APPLIED, Boolean.TRUE); 

    if(request.getParameter(actionParameter) !=null && 
     request.getParameter(actionParameter).equals("logout")) { 
     SecurityContextHolder.clearContext(); 
     return; 
    } 

    if (!requiresAuthentication(request, response)) { 
     chain.doFilter(request, response); 
     return; 
    } 

    Authentication authResult; 
    try { 
     authResult = attemptAuthentication(request, response); 
     if (authResult == null) { 
     return; 
     } 
    } catch (AuthenticationException failed) { 
     unsuccessfulAuthentication(request, response, failed); 
     return; 
    } 

    try { 
     successfulAuthentication(request, response, chain, authResult); 
    } catch (NestedServletException e) { 
     if(e.getCause() instanceof AccessDeniedException) { 
     unsuccessfulAuthentication(request, response, new LockedException("Forbidden")); 
     } 
    } 
    } 

    @Override 
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { 

    AbstractAuthenticationToken userAuthenticationToken = authUserByToken(this.token); 
    if(userAuthenticationToken == null) 
     throw new AuthenticationServiceException(MessageFormat.format("Error | {0}", "Bad Token")); 

    return userAuthenticationToken; 
    } 

    private AbstractAuthenticationToken authUserByToken(String tokenRaw) { 
    AbstractAuthenticationToken authToken = null; 
    try { 
     // check your input token, identify the user 
     // if success create AbstractAuthenticationToken for user to return 
     // eg: 
     authToken = new UsernamePasswordAuthenticationToken(username, userHash, userAuthorities); 

    } catch (Exception e) { 
     logger.error("Error during authUserByToken", e); 
    } 
    return authToken; 
    } 

    @Override 
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, 
              Authentication authResult) throws IOException, ServletException { 
    SecurityContextHolder.getContext().setAuthentication(authResult); 

    getSuccessHandler().onAuthenticationSuccess(request, response, authResult); 
    } 

} 

और कस्टम SuccessHandler और यह तार की तरह कस्टम AuthenticationFilter को लागू करने की जरूरत है।

+0

वसंत सुरक्षा पर कोई टोकन आधारित प्रमाणीकरण फ़िल्टर नहीं है ?? – Rafael

4

आप वसंत सुरक्षा में निम्नलिखित सेम का उपयोग कर ऐसा कर सकते हैं TimedKeyBasedPersistenceTokenService

<bean name="tokenService" class="com.digipos.security.core.token.TimedKeyBasedPersistenceTokenService"> 
    <property name="tokenLifeInMinutes" value="15000"/> 
    <property name="serverSecret" value="1234567"/> 
    <property name="serverInteger" value="15062013"/> 
    <property name="pseudoRandomNumberBits" value="7"/> 
    <property name="secureRandom" ref="secureRandom"/> 
</bean> 


<bean name="secureRandom" class="java.security.SecureRandom"> 
    <property name="seed" value="122"/> 
</bean> 

अलावा आप भी

की जरूरत है कि Http403ForbiddenEntryPoint सेम के लिए एक PreAuthenticatedAuthenticationProvider

और entry-point-ref<http> की विशेषता का उपयोग

+0

मुझे इस टोकन आधारित प्रमाणीकरण में बहुत दिलचस्पी है लेकिन प्रीएट प्रमाणीकृत प्रमाणीकरणप्रदाता के साथ संबंध को समझ में नहीं आता है ... प्रमाणीकरण के लिए टोकन को सत्यापित करने की आवश्यकता नहीं है? ... क्या आप इसे थोड़ा और विस्तारित कर सकते हैं? – Rafael

1

मुझे एक आसान तरीका मिला है:

मेरा समाधान टोकन प्रमाणीकरण के लिए काम करता है, और प्रमाणीकरण फार्म करता है, लेकिन यदि आप चाहें तो आसानी से उनमें से एक को अक्षम कर सकते हैं।

मेरा फ़िल्टर रोमन के फ़िल्टर के समान है, लेकिन मुझे उपयोगकर्ता को किसी विशेष संसाधन तक पहुंचने की आवश्यकता नहीं है, कोई लॉगआउट भी नहीं है -> वसंत सुरक्षा के लिए पारित किया गया है।

प्रमाणन फिल्टर:

public class TokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter { 

private static final String SECURITY_TOKEN_KEY = "token"; 
private static final String SECURITY_TOKEN_HEADER = "X-Token"; 

public TokenAuthenticationFilter() { 

    super("/"); 
} 

@Override 
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 

    HttpServletRequest request = (HttpServletRequest) req; 
    HttpServletResponse response = (HttpServletResponse) res; 

    String token = request.getParameter(SECURITY_TOKEN_KEY); 
    // or this.token = request.getHeader(SECURITY_TOKEN_HEADER); 

    if (token != null) { 

     Authentication authResult; 
     try { 
      authResult = attemptAuthentication(request, response, token); 
      if (authResult == null) { 
       notAuthenticated(request, response, new LockedException("User Not found")); 
       return; 
      } 
     } catch (AuthenticationException failed) { 
      notAuthenticated(request, response, failed); 
      return; 
     } 

     try { 
      successfulAuthentication(request, response, chain, authResult); 
      return; 
     } catch (NestedServletException e) { 
      logger.error(e.getMessage(), e); 
      if (e.getCause() instanceof AccessDeniedException) { 
       notAuthenticated(request, response, new LockedException("Forbidden")); 
       return; 
      } 
     } 
    } 
    chain.doFilter(request, response);// return to others spring security filters 
} 

public void notAuthenticated(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException { 

    response.sendRedirect("http://www.google.ro"); 
    // unsuccessfulAuthentication(request, response, failed); 
} 

public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response, String token) throws AuthenticationException, IOException, ServletException { 

    AbstractAuthenticationToken userAuthenticationToken = authUserByToken(token); 
    if (userAuthenticationToken == null) 
     throw new AuthenticationServiceException(MessageFormat.format("Error | {0}", "Bad Token")); 

    return userAuthenticationToken; 
} 

private AbstractAuthenticationToken authUserByToken(String tokenRaw) { 

    AbstractAuthenticationToken authToken = null; 
    try { 
     // check your input token, identify the user 
     // if success create AbstractAuthenticationToken for user to return 
     // eg: 
     // authToken = new UsernamePasswordAuthenticationToken(username, userHash, userAuthorities); 
     // authToken = new UsernamePasswordAuthenticationToken(tokenRaw, authToken,) 
     logger.info("token received = " + tokenRaw); 
     // obtain user by your methods 
     // if (user != null) { 
     // SecurityUser securityUser = new SecurityUser(user); 
     // return new PreAuthenticatedAuthenticationToken(securityUser, securityUser.getPassword(), securityUser.getAuthorities()); 
     // } 
    } catch (Exception e) { 
     logger.error("Error during authUserByToken", e); 
    } 
    return authToken; 
} 

@Override 
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, Authentication authResult) throws IOException, ServletException { 

    SecurityContextHolder.getContext().setAuthentication(authResult); 

    new CustomAuthenticationSuccessHandler().onAuthenticationSuccess(request, response, authResult); 
} 

@Override 
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { 

    logger.error("No TOKEN PROVIDED"); 
    return null; 
    } 

} 

तो सब आप इस फिल्टर springSecurity (addFilterBefore) में यह विन्यस्त करने है मैप करने के लिए क्या करना है, इस सर्वलेट config में मैप किया जाने वाला नहीं है।

 http.authorizeRequests().antMatchers("/login*").permitAll(); 
     http.authorizeRequests().antMatchers("/register*").permitAll(); 

     http.authorizeRequests().antMatchers("/admin/**").hasAnyAuthority("ROLE_ADMIN", "ROLE_USER");// 

     http.authorizeRequests().and().formLogin()// 
       .loginPage("/login")// 
       .successHandler(successHandler())// 
       .failureUrl("/login?error").permitAll()// 
       .and().logout()// 
       .logoutUrl("/logout").logoutSuccessUrl("/login?logout").permitAll()// 
       .and().rememberMe().key(applicationName + "_key").tokenValiditySeconds(2419200); // remember me for 2 weeks 

     http.addFilterBefore(new TokenAuthenticationFilter(), AnonymousAuthenticationFilter.class); 
+0

मेरे पास इस सब पर सवाल है? जब बैकएंड पर टोकन उत्पन्न होता है, तो टोकन उत्पन्न होता है, और बैकएंड पर इसे कैसे संग्रहीत/रखा जा रहा है? यह कितने समय के लिए है? और जब हमें बैकएंड के साथ बैकएंड के लिए AJAX अनुरोध मिलता है ... मुझे लगता है कि टोकन स्टोर से टोकन को देखने के लिए हमारे पास कुछ कोड है, क्या यह सही है?जब बैकएंड पर टोकन उत्पन्न होता है और संग्रहीत होता है, जब हम सामने के अंत में टोकन भेजते हैं, तो क्या आप इसे कुकी के रूप में स्टोर करते हैं? क्या होगा यदि कुकीज़ बंद कर दी गई हो? धन्यवाद! – tjholmes66