Spring Security and JSON Authentication

前端 未结 8 1589
我在风中等你
我在风中等你 2020-11-28 05:11

I\'ve an application in spring/spring-mvc that totally uses JSON communications. Now I need to authenticate my application with spring security 3 (that uses LdapAuthenticati

相关标签:
8条回答
  • 2020-11-28 05:48

    According with Kevin suggestions,
    and after reading this posts: 1, 2, documentation 3, and thanks to this blog post,
    I wrote my own FORM_LOGIN_FILTER to directly manage JSON before authentication.
    I paste my code for the community.

    The goal is to grant both the classical browser form POST authentication with JSON based authentication. Also in JSON authentication I want to avoid the redirect to loginSuccesful.htm

    In context:

    <security:http use-expressions="true" auto-config="false" entry-point-ref="http403EntryPoint">      
        <security:intercept-url pattern="/logs/**" access="denyAll" />
        <!-- ... All other intercept URL -->
    
        <security:custom-filter ref="CustomUsernamePasswordAuthenticationFilter" position="FORM_LOGIN_FILTER "/>
        <security:logout
                invalidate-session="true"
                logout-success-url="/LogoutSuccessful.htm"
                delete-cookies="true"
        />
        <security:session-management>
            <security:concurrency-control max-sessions="1" error-if-maximum-exceeded="true" />
        </security:session-management>
        <security:access-denied-handler error-page="/accessDenied.htm" />
    </security:http>
    
    <bean id="CustomUsernamePasswordAuthenticationFilter" class="path.to.CustomUsernamePasswordAuthenticationFilter">
        <property name="authenticationManager" ref="authenticationManager" />
        <property name="authenticationSuccessHandler" ref="customSuccessHandler"/>
        <property name="authenticationFailureHandler" ref="failureHandler"/>
        <property name="filterProcessesUrl" value="/j_spring_security_check"/>
        <property name="usernameParameter" value="j_username"/>
        <property name="passwordParameter" value="j_password"/>
    </bean>
    
    <bean id="customSuccessHandler" class="path.to.CustomAuthenticationSuccessHandler">
        <property name="defaultTargetUrl" value="/login.htm" />
        <property name="targetUrlParameter" value="/LoginSuccessful.htm" />
    </bean>
    
    <bean id="failureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
        <property name="defaultFailureUrl" value="/login.htm" />
    </bean>
    
    <bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint" />
    

    CustomUsernamePasswordAuthenticationFilter class:

    public class CustomUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
        private String jsonUsername;
        private String jsonPassword;
    
        @Override
        protected String obtainPassword(HttpServletRequest request) {
            String password = null; 
    
            if ("application/json".equals(request.getHeader("Content-Type"))) {
                password = this.jsonPassword;
            }else{
                password = super.obtainPassword(request);
            }
    
            return password;
        }
    
        @Override
        protected String obtainUsername(HttpServletRequest request){
            String username = null;
    
            if ("application/json".equals(request.getHeader("Content-Type"))) {
                username = this.jsonUsername;
            }else{
                username = super.obtainUsername(request);
            }
    
            return username;
        }
    
        @Override
        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response){
            if ("application/json".equals(request.getHeader("Content-Type"))) {
                try {
                    /*
                     * HttpServletRequest can be read only once
                     */
                    StringBuffer sb = new StringBuffer();
                    String line = null;
    
                    BufferedReader reader = request.getReader();
                    while ((line = reader.readLine()) != null){
                        sb.append(line);
                    }
    
                    //json transformation
                    ObjectMapper mapper = new ObjectMapper();
                    LoginRequest loginRequest = mapper.readValue(sb.toString(), LoginRequest.class);
    
                    this.jsonUsername = loginRequest.getUsername();
                    this.jsonPassword = loginRequest.getPassword();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
            return super.attemptAuthentication(request, response);
        }
    }
    

    CustomAuthenticationSuccessHandler class:

    public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
    
        public void onAuthenticationSuccess(
                HttpServletRequest request,
                HttpServletResponse response,
                Authentication auth
        )throws IOException, ServletException {
    
            if ("application/json".equals(request.getHeader("Content-Type"))) {
                /*
                 * USED if you want to AVOID redirect to LoginSuccessful.htm in JSON authentication
                 */         
                response.getWriter().print("{\"responseCode\":\"SUCCESS\"}");
                response.getWriter().flush();
            } else {
                super.onAuthenticationSuccess(request, response, auth);
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-28 05:49

    I applied the answers from fl4l and oe.elvik for login with JSON credentials in a Spring Boot application. I am working with annotation-based bean configuration.

    In the referenced answers, a custom filter is created in which the authentication manager is injected. To do this, the authentication manager must be present as a Spring Bean. Here is a link on how to do that: https://stackoverflow.com/a/21639553/3950535.

    0 讨论(0)
提交回复
热议问题