简体   繁体   中英

csrf token in react router

I am using react and spring security and want to pass csrf token when user click on logout button. Any suggestion how to include csrf token in react. I have searched for the solution on google but not getting any solution.

import React from 'react';
import { IndexLink, Link } from 'react-router';

const Nav = (props) => (
      <nav className="navbar navbar-inverse navbar-fixed-top">
        <div className="container-fluid">
          <div className="navbar-header">
              <a className="navbar-brand" href="#">GoRFQ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</a>
          </div>
          <ul className="nav navbar-nav">
          <li ><Link onlyActiveOnIndex activeStyle={{color:'#052426'}} to='/'>Home</Link></li>
          <li ><Link activeStyle={{color:'#052426'}} to='/boms'>BOMs</Link></li>
          <li class="dropdown"><a href="javascript:void(0)" class="dropbtn">Quotes</a>
            <div class="dropdown-content">
              <Link activeStyle={{color:'#052426'}} to='/quotesin' >Incoming Quotes</Link>
              <Link activeStyle={{color:'#052426'}} to='/quotesout' >Outgoing Quotes</Link>
            </div>
          </li>
          <li class="dropdown"><a href="javascript:void(0)" class="dropbtn">Requests</a>
            <div class="dropdown-content">
              <Link activeStyle={{color:'#052426'}} to='/requestsin' >Received Requests</Link>
              <Link activeStyle={{color:'#052426'}} to='/requestsout' >Sent Requests</Link>
            </div>
          </li>
          <li ><Link activeStyle={{color:'#052426'}} to='/upload'>Upload BOM</Link></li>
          <li ><Link activeStyle={{color:'#052426'}} to='/contacts'>Contacts</Link></li>
          <li ><Link activeStyle={{color:'#052426'}} to='/profile'>My Profile</Link></li>
          <li ><Link activeStyle={{color:'#052426'}} to='/about'>About</Link></li>
          </ul>

          <form action="/perform-logout" method="post" className="pull-right">
             <input type="submit" className="btn btn-primary" value="Sign Out"/>

          </form>


        </div>
      </nav>
);

export default Nav; 

I forgot to share the answer that how I made it work, so it will help someone else. I did following things:

1) I installed react-cookie.

2) In my react component I imported this react-cookie

import Cookie from 'react-cookie';

3) Extracted the XSRF-TOKEN from cookie and passed as hidden field in form

<form action="/perform-logout" method="post">
                  <input type="hidden" name="_csrf" value={Cookie.load('XSRF-TOKEN')}/>
                   <input type="submit" className="btn btn-primary btn-block" value="Sign Out"/>
                </form> 

And it worked.

you can add the follow config in the spring security

http.csrf().csrfTokenRepository(csrfTokenRepository().withHttpOnlyFalse())
                .and()
                .addFilterAfter(csrfHeaderFilter(), SessionManagementFilter.class)
                .addFilterAfter(new CsrfHeaderFilter(), CsrfFilter.class);

private Filter csrfHeaderFilter() {
        return new OncePerRequestFilter() {
            @Override
            protected void doFilterInternal(HttpServletRequest request,
                                            HttpServletResponse response, FilterChain filterChain)
                    throws ServletException, IOException {
                CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
                        .getName());
                if (csrf != null) {
                    Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
                    String token = csrf.getToken();
                    if (cookie == null || token != null
                            && !token.equals(cookie.getValue())) {
                        cookie = new Cookie("XSRF-TOKEN", token);
                        cookie.setPath("/");
                        response.addCookie(cookie);
                    }
                }
                filterChain.doFilter(request, response);
            }
        };
    }

    private CsrfTokenRepository csrfTokenRepository() {
        HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
        repository.setHeaderName("X-XSRF-TOKEN");
        return repository;
    }

The csrfHeaderFilter will add the csrf token to the response in XSRF-TOKEN and send to the client's cookies. the next time client read XSRF-TOKEN token in the cookies and put it in http request header in with key X-XSRF-TOKEN, spring will use the CsrfTokenRepository to find X-XSRF-TOKEN in client header .

the withHttpOnlyFalse() method set the httpOnly to false, it mean that the js client can read the csrf token in the client's cookies, if not, the js client can not read it,may be the default is withHttpOnlyFalse().

You can look at https://spring.io/guides/tutorials/spring-security-and-angular-js/.It sumit the csrftoken with a angular client. But i think it almost the same if you use the react client. Hope can help you.

In your spring web security config add the following lines

http.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
http.addFilterAfter(new CsrfTokenResponseHeaderBindingFilter(), CsrfFilter.class);

You can find the filter is here: https://github.com/aditzel/spring-security-csrf-filter

I use reactjs and you don't have to do anything on the UI side, it just works

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM