RYJ
RYJ

Reputation: 439

How to save authenticated username into a database

I'm just a beginner to Spring and Spring Security. Here I'm creating a Spring MVC application with Spring Security. I just want to save authenticated username into a database. Using following form I'm getting the logged username. But I don't know how to save that username using path="" attribute.

This is the form

<form:form modelAttribute="reservation">
    <div>
        <label for="name">Name</label>

        <sec:authentication var="user" property="principal" />
        <sec:authorize  access="isAuthenticated()">
            ${user.username}
        </sec:authorize> 
    </div>
    <div>
        <label for="emailAddress">Email</label>
        <form:input path="emailAddress"/>
    </div>

Here is the controller

@RequestMapping(value="/flight-reservation", method={RequestMethod.POST})
public String doReservation(@Valid @ModelAttribute("reservation") FlightReservation reservation ,BindingResult result){
    if(result.hasErrors()){
        return "flight-reservation";
    }
    reservationService.save(reservation);
    return "redirect://flight-reservation.html?ok=true";
}

I can save email using path="emailAddress" But my question is how to save that logged username using path of something else. I appreciate your help.

Upvotes: 0

Views: 364

Answers (1)

Serge Ballesta
Serge Ballesta

Reputation: 148890

Thanks to Spring security integration in Spring MVC, you directly get principal as a controller parameter:

@RequestMapping(value="/flight-reservation", method={RequestMethod.POST})
public String doReservation(@Valid @ModelAttribute("reservation") FlightReservation reservation,
        BindingResult result, @AuthenticationPrincipal Principal principal){
    // use principal (Authentication.getPrincipal) to extract user name and use it
    ....

This one is valid since Spring Security 3.2 If you use an older version, you must use the SecurityContextHolder:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
Principal principal = authentication == null ? null : authentication.getPrincipal();

Assuming that your authentication object returns a UserDetails, you could use it that way:

@RequestMapping(value="/flight-reservation", method={RequestMethod.POST})
public String doReservation(@Valid @ModelAttribute("reservation")
        FlightReservation reservation ,BindingResult result,
        @AuthenticationPrincipal UserDetails details){
    if(result.hasErrors()){
        return "flight-reservation";
    }
    reservation.setUser(details.getUserName); // adapt it to your real classes...
    reservationService.save(reservation);
    return "redirect://flight-reservation.html?ok=true";
}

That mean you use ${user.username} in the JSP to display current authenticated user name, but you get it directly from Spring security in your controller, store it in your reservation object that already contains the other fields initialized via the form and pass the object containing th user name (or whatever it contains representing the authenticated user) to the service. That way, Spring security guarantees that the user written in the database is the authenticated user even it somenone tries to send a forged request.


Alternatively, Spring Framework Reference explicitely says that you can pass a Principal parameter to a @RequestMapping annotated method, and the parameter will recieve the currently authenticated user. In fact you get request.getUserPrincipal that was populated with the Spring Security Authentication

So you can simply write:

@RequestMapping(value="/flight-reservation", method={RequestMethod.POST})
public String doReservation(@Valid @ModelAttribute("reservation") FlightReservation reservation,
        BindingResult result, Principal principal){
    Authentication auth = (Authentication) principal;

or directly as Authentication implements Principal

@RequestMapping(value="/flight-reservation", method={RequestMethod.POST})
public String doReservation(@Valid @ModelAttribute("reservation") FlightReservation reservation,
        BindingResult result, Authentication auth){

and get the user name from there.

Upvotes: 1

Related Questions