DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
  1. DZone
  2. Coding
  3. Frameworks
  4. Using RESTful URLs on your Spring 3 MVC Webapp

Using RESTful URLs on your Spring 3 MVC Webapp

Roger Hughes user avatar by
Roger Hughes
·
Sep. 21, 11 · Interview
Like (0)
Save
Tweet
Share
12.02K Views

Join the DZone community and get the full member experience.

Join For Free

 This blog comes as an answer to a question from a reader. Now, as a rule, I don’t do request blogs, but I thought that this sounded like an interesting topic. The question refers to my blog from July 11 on accessing request parameters using Spring 3 MVC and was “Do you know how to encode the uuid so it is not visible to the user for security concerns?”. The answer is “Yes”, but that would make for a very short blog.

In this case I’m assuming that the question is talking about using RESTful URLs to maintain session state information between pages. REST is a subject that’s had many words written about it, but putting it in very simplistic terms I’m defining it as not storing session or state information on your web server between browser calls. Even more simply put, it means not using the HttpSession interface implementations. Not maintaining state on the server gives you at least two obvious benefits; the first being improved loading. This is because your server is not using memory for storing state data which may, or may not be needed. The second benefit is scaling. If you’re using a domain with multiple servers, then tying session state to one server is problematic as you can’t usually guarantee that subsequent sequential calls to the domain will be directed to the same physical server.

There are various techniques use to solve this problem, including making everything form based and storing state information in hidden fields, using cookies, and manipulating URLs. This blog demonstrates the third technique of encrypting state data and tagging it onto the end of a URL, so that it’s passed back and forth between the browser and the server as a request parameter:

http://www.mywebsite.com/thepageIwant?session=ThisIsEncodedData
An example scenario for this technique would an e-commerce site. In this case, you’d select a couple of items and add them to your basket. You’d then login and review your basket and then perhaps modify the delivery address before proceeding to pay. In doing all this, you conceptually remain logged in to the server but, in the RESTful world, the server doesn’t remember you.

This example uses three screens to demonstrate this idea. The first screen logs you in, the second contains a URL that includes some session data, and the third displays the session data for review.


The screen shot above shows a simple login screen. Note that I’ve used a clear text password for demonstration purposes only.


The second screen in this scenario is the one that contains the encrypted session information; namely the user name and password, which has both been displayed and glued on to the end of the href of an anchor tag.


The last screen shows the decoded session information demonstrating that we’ve still got it and that it’s correct.

Moving on to the actual Java code for this demo... The simple bean below I’ve called Session and it holds all the state data we want encoding.

public class Session {

  private static final String SEP = "=/=";

  private String name;
  private String password;

  public Session() {
    // Blank
  }

  public Session(String combined) {

    String[] split = combined.split(SEP);
    name = split[0];
    password = split[1];
  }

  public String getName() {
    return name;
  }

  public void setName(String username) {
    this.name = username;
  }

  public String getPassword() {
    return password;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  @Override
  public String toString() {
    return name + SEP + password;
  }
}

If you look at the code above, you’ll see that it contains two features that give it context in the application. The toString(...) returns a string that the application can encode and the single argument constructor can create a full bean from its argument.

This works cohesively with the controller code, which is shown below...
@Controller
public class RewriteController {

  private static final String ENCODING_KEY = "ThisWillBeTheKey";

  /**
   * Create the initial blank form
   */
  @RequestMapping(value = "/loginform", method = RequestMethod.GET)
  public String getCreateForm(Model model) {

    model.addAttribute("Session", new Session());
    return "login.page";
  }

  /**
   * This is where you login...
   */
  @RequestMapping(value = "/login", method = RequestMethod.POST)
  public String login(Session userDetails, Model model)
      throws UnsupportedEncodingException {

    byte[] encodedBytes = encodeURL(userDetails);
    String encodedURL = new String(Base64.encodeBase64(encodedBytes));
    model.addAttribute("encodedURL", encodedURL);

    return "display.encoded.url";
  }

  private byte[] encodeURL(Session userDetails)
      throws UnsupportedEncodingException {

    RC4Lite rc4 = getRC4Lite();

    byte[] in = userDetails.toString().getBytes("UTF8");
    byte[] out = new byte[in.length];

    rc4.encrypt(in, 0, out, 0, in.length);

    return out;
  }

  private RC4Lite getRC4Lite() throws UnsupportedEncodingException {
    RC4Lite rc4 = new RC4Lite();
    rc4.setKey(ENCODING_KEY.getBytes("UTF8"));
    return rc4;
  }

  /**
   * This is where you're still in the REST session and re-validate the user
   */
  @RequestMapping(value = "/decode", method = RequestMethod.GET)
  public String someSessionMethod(
      @RequestParam(value = "session") String sessionParam, Model model)
      throws UnsupportedEncodingException {

    byte[] encodedBytes = Base64
        .decodeBase64(sessionParam.getBytes("UTF8"));
    String decodedString = decodeURL(encodedBytes);

    Session session = new Session(decodedString);
    model.addAttribute(session);

    return "display.decoded.url";
  }

  private String decodeURL(byte[] encodedBytes)
      throws UnsupportedEncodingException {

    RC4Lite rc4 = getRC4Lite();

    byte[] out = new byte[encodedBytes.length];
    rc4.decrypt(encodedBytes, 0, out, 0, encodedBytes.length);

    return new String(out);
  }
}

The controller class above contains three handler methods. The first handler method, getCreateForm(...), is fairly straight forward and simply adds a Session bean the model before displaying the login in form. The second handler method, login(...),
is where all the action takes place. There are two parts to encoding the session data (the name and password). Part one is to encrypt the data and for that I’ve simply borrowed my RC4Lite class from my RC4 Encryption blog1. Once encrypted, the RC4 bytes will need converting into ASCII and for that I’ve used Apache’s Base64 class as described in my base64 blog. Converting to ASCII ensures that the characters are printable and don’t cause any problems. The string is then added to the model where it’s attached to the anchor tag as shown in the following JSP snippet:

<a href='decode?session=${encodedURL}' } ><spring:message code="label.the.next.page"/></a>

The final handler method, someSessionMethod(...) receives the input from the above link, decodes it using a reverse process to encoding It then creates a new Session object and puts that into the model, which is then displayed on the final page.

Remember that this is only a sample, it just demonstrates the idea of encrypting session information and adding to a URL as a parameter. There are improvements you could make here, for example: using a interceptor to authenticate with the server upon each request before doing the business logic in the controller, or using a better encryption class, but in essence the principle applies to any webapp. There are also other techniques you can use for achieving secure web communications, so more on those later perhaps...


1 There are better ways of doing encryption than RC4, it's used here only for convenience in this demonstration.

From http://www.captaindebug.com/2011/09/using-restful-urls-on-your-spring-3-mvc.html

REST Web Protocols Spring Framework Session (web analytics)

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • Build an Automated Testing Pipeline With GitLab CI/CD and Selenium Grid
  • Seamless Integration of Azure Functions With SQL Server: A Developer's Perspective
  • 19 Most Common OpenSSL Commands for 2023
  • How Chat GPT-3 Changed the Life of Young DevOps Engineers

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: