Spring Security(Third Edition)
上QQ阅读APP看书,第一时间看更新

The SpringSecurityUserContext interface

The current UserContext implementation, UserContextStub, is a stub that always returns the same user. This means that the My Events page will always display the same user no matter who is logged in. Let's update our application to utilize the current Spring Security user's username, to determine which events to display on the My Events page.

You should be starting with the sample code in chapter03.00-calendar.

Take a look at the following steps:

  1. The first step is to comment out the @Component attribute on UserContextStub, so that our application no longer uses our scanned results.

The @Component annotation is used in conjunction with the @ComponentScan annotation found in com/packtpub/springsecurity/web/configuration/WebMvcConfig.java, to automatically create a Spring bean rather than creating an explicit XML or Java configuration for each bean. You can learn more about the classpath of Spring scanning in the Spring Reference link at http://static.springsource.org/spring/docs/current/spring-framework-reference/html/.

Take a look at the following code snippet:

        //src/main/java/com/packtpub/springsecurity/service/UserContextStub.java

...
//@Component
public class UserContextStub implements UserContext {
...
  1. The next step is to utilize SecurityContext to obtain the currently logged-in user. We have included SpringSecurityUserContext within this chapter's code, which is wired up with the necessary dependencies but contains no actual functionality.
  2. Open the SpringSecurityUserContext.java file and add the @Component annotation. Next, replace the getCurrentUser implementation, as illustrated in the following code snippet:
        //src/main/java/com/packtpub/springsecurity/service/
SpringSecurityUserContext.java

@Component
public class SpringSecurityUserContext implements UserContext {
private final CalendarService calendarService;
private final UserDetailsService userDetailsService;
@Autowired
public SpringSecurityUserContext(CalendarService calendarService,
UserDetailsService userDetailsService) {
this.calendarService = calendarService;
this.userDetailsService = userDetailsService;
}
public CalendarUser getCurrentUser() {
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
if (authentication == null) {
return null;
}
String email = authentication.getName();
return calendarService.findUserByEmail(email);
}
public void setCurrentUser(CalendarUser user) {
throw new UnsupportedOperationException();
}
}

Our code obtains the username from the current Spring Security Authentication object and utilizes that to look up the current CalendarUser object by email address. Since our Spring Security username is an email address, we are able to use the email address to link CalendarUser with the Spring Security user. Note that if we were to link accounts, we would normally want to do this with a key that we generated rather than something that may change (that is, an email address). We follow the good practice of returning only our domain object to the application. This ensures that our application is only aware of our CalendarUser object and thus is not coupled to Spring Security.

This code may seem eerily similar to when we used the sec:authorize="isAuthenticated()"
tag attribute in Chapter 2, Getting Started with Spring Security, to display the current user's username. In fact, the Spring Security tag library uses SecurityContextHolder in the same manner as we have done here. We could use our UserContext interface to place the current user on HttpServletRequest and thus remove our dependency on the Spring Security tag library.

  1. Start up the application, visit http://localhost:8080/, and log in with admin1@example.com as the username and admin1 as the password.
  2. Visit the My Events page, and you will see that only the events for that current user, who is the owner or the attendee, are displayed.
  3. Try creating a new event; you will observe that the owner of the event is now associated with the logged-in user.
  4. Log out of the application and repeat these steps with user1@example.com as the username and user1 as the password.

Your code should now look like chapter03.01-calendar.