1

I have a login form on my site and it is set up to show every time user wants to open any resource on my webpage.

When user goes to e.g. myweb.page/some/resource it shows him my login form and then - after providing credentials - it should redirect him to the requested url with additional j_security_check part of the url. This is my code so far:

import React from "react";

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({[event.target.name]: event.target.value});
  }

  handleSubmit(event) {
    let target = "";
    let targetResource = getQueryVariable('resource');
    if (targetResource) {
        if (targetResource.substr(-1) === '/') {
            target = targetResource.substr(0, -1);
        } else {
            target = targetResource;
        }
    }
    alert(targetResource);
    this.state.target = targetResource
  }

  render() {
    return (
      <form onSubmit={ this.handleSubmit } action={this.state.target + "/j_security_check"} method="POST">
        <label>
          email:
          <input type="text" name="email" value={this.state.email} onChange={e=>this.handleChange(e)} />
        </label>
        <input type="hidden" name="resource" value={this.state.target + "/j_security_check"} />
        <label>
          passwords:
          <input type="password" name="password" value={this.state.password} onChange={e=>this.handleChange(e)} />
        </label>
        <input type="submit" value="Login" />
      </form>
    );
  }
}

function getQueryVariable(variable)
{
    var query = window.location.search.substring(1);
    console.log(query)
    var vars = query.split("&");
    console.log(vars)
    for (var i=0;i<vars.length;i++) {
        var pair = vars[i].split("=");
        console.log(pair);
        if(pair[0] == variable){
            return pair[1];
        }
    }
    return(false);
}

export default App;

In handleSubmit method there's an alert that prints the correct redirection path, e.g.:

%2Fcorrect%2Furl%2Faddress

but then the webpage reloads and it redirects to:

http://localhost:8080/apps/myLoginForm/undefined/j_security_check

instead of

http://localhost:8080/apps/myLoginForm/correct/url/address/j_security_check

Why is the correct redirection target not passed to the url in the form? Thanks!

1 Answer 1

1

The reason is probably because the form is submitted while the action is still action={this.state.target + "/j_security_check"} which makes is 'undefined/j_security_check'.

I'd recommend using event.preventDefault() in the handleSubmit code and then just performing the data call and then redirect yourself afterwards if you can't calculate the URL before the user submits.. This also works better if you are using React in its capacity as a SPA.

Otherwise just calculate the target location in render or in a memoized function if it's time consuming to calculate. That way the form will have the correct url to post to.

Update:

Here's an example of how you would just put it in the render function since it doesn't perform too much work.

Edit: added decodeURIComponent() to the getTargetURL() function, and removed the rest of this.handleSubmit as I'm fairly sure it isn't needed anymore.

import React from 'react';

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: '' };

    this.handleChange = this.handleChange.bind(this);
  }

  handleChange(event) {
    this.setState({ [event.target.name]: event.target.value });
  }

  render() {
    const target = getTargetURL();
    return (
      <form
        action={target + '/j_security_check'}
        method="POST"
      >
        <label>
          email:
          <input
            type="text"
            name="email"
            value={this.state.email}
            onChange={(e) => this.handleChange(e)}
          />
        </label>
        <input
          type="hidden"
          name="resource"
          value={target + '/j_security_check'}
        />
        <label>
          passwords:
          <input
            type="password"
            name="password"
            value={this.state.password}
            onChange={(e) => this.handleChange(e)}
          />
        </label>
        <input type="submit" value="Login" />
      </form>
    );
  }
}

function getTargetURL() {
  let target;
  const targetResource = decodeURIComponent(getQueryVariable('resource'));
  if (targetResource) {
    if (targetResource.substr(-1) === '/') {
      target = targetResource.substr(0, -1);
    } else {
      target = targetResource;
    }
  }
  return target;
}

function getQueryVariable(variable) {
  var query = window.location.search.substring(1);
  console.log(query);
  var vars = query.split('&');
  console.log(vars);
  for (var i = 0; i < vars.length; i++) {
    var pair = vars[i].split('=');
    console.log(pair);
    if (pair[0] == variable) {
      return pair[1];
    }
  }
  return false;
}

export default App;
Sign up to request clarification or add additional context in comments.

4 Comments

Hi Zachary, thanks for your answer - since I'm quite new to react, could you please show me some example code? I didn't understand exactly how could I fix it... Thank you!
thanks, it works, I just see that I should probably leave the empty method handleSubmit() in the code, right? I see that you removed it in your code. Also, one last thing - it redirects me now to myLoginForm%2Fcorrect%2Furl%2Ftarget/j_security_check instead of myLoginForm/correct/url/address/j_security_check - do you know how to fix that, so that instead of %2F instead of / ? Thank you!
Okay, I've fixed the issues you were having. Also, I believe that you shouldn't need handleSubmit at all anymore and I completely removed all references to it in the code like I had meant to do originally.
thank you very much, it works as expected, you made my afternoon! :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.