We are going to have a look at how to create our own annotation to secure some commands. When we annotate a command with our annotation, it will make sure that user needs to authenticated in order to use it. It is going to look like this.
@Secured
@ShellMethod(key = "logout", value = "Logout from GitHub. Usage: logout")
public void logout() {
sessionHolder.removeCurrentSession();
}
First, create build.gradle with all needed dependencies.
Now we need to create the new annotation @Secured.
Then we create an aspect that will add required functionality to @Secure annotation. In the aspect, we want to make sure a session exists before the annotated method is invoked. If session does not exist, we throw an exception to indicate user needs to authenticate first.
In SecuredAspect class, there is usage of SessionHolder bean. sessionHolder bean is a singleton by default and it holds a session. Here is how such a class could look like.
Here is the implementation.
And here the session object.
When user login operation is successful, we set a value in the session holder. It could look like this.
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class DefaultSessionHolder implements SessionHolder {
private Session session;
@Override
public void setCurrentSession(Session session) {
this.session = session;
}
@Override
public Optional<Session> getCurrentClientSession() {
return Optional.ofNullable(session);
}
@Override
public void removeCurrentSession() {
session = null;
}
}
public class Session {
private final String authToken;
public Session(String authToken) {
this.authToken = authToken;
}
public String getAuthToken() {
return authToken;
}
}
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;
import org.springframework.shell.standard.ShellOption;
import shell.features.auth.service.AuthResponse;
import shell.features.auth.service.AuthService;
import shell.security.annotation.Secured;
import shell.security.session.Session;
import shell.security.session.SessionHolder;
import java.util.Optional;
@ShellComponent
public class AuthCommand {
private final AuthService authService;
private final SessionHolder sessionHolder;
public AuthCommand(AuthService authService, SessionHolder sessionHolder) {
this.authService = authService;
this.sessionHolder = sessionHolder;
}
@ShellMethod(key = "login", value = "Login into GitHub. Usage: login <your login> <your password>")
public String authenticate(@ShellOption String login,
@ShellOption String password) {
Optional<AuthResponse> response = authService.authenticate(login, password);
if (response.isPresent()) {
AuthResponse authResponse = response.get();
sessionHolder.setCurrentSession(new Session(authResponse.getAuthToken()));
return "Success.";
} else {
return "Failed to authenticate.";
}
}
@Secured
@ShellMethod(key = "logout", value = "Logout from GitHub. Usage: logout")
public void logout() {
sessionHolder.removeCurrentSession();
}
}