Статьи

Внедрение аутентифицированного пользователя в Spring MVC @Controllers

Внедрение аутентифицированного пользователя в метод-обработчик Spring MVC может быть сделано с @AuthenticationPrincipal аннотации @AuthenticationPrincipal и AuthenticationPrincipalArgumentResolver который является реализацией Spring MVS MethodArgumentResolver . AuthenticationPrincipalArgumentResolver регистрируется по умолчанию в конфигурации веб-безопасности (например, когда вы включаете защиту с помощью @EnableWebSecurity ).

1. Пользовательские UserDetails

Давайте предположим, что у нас есть собственная реализация UserDetails :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import org.springframework.security.core.GrantedAuthority;
import pl.codeleak.surveyapp.entities.Member;
 
import java.util.Collection;
 
public class AccountDetails
    extends org.springframework.security.core.userdetails.User {
 
    private final Account account;
 
    public AccountDetails(Account account,
                          Collection<? extends GrantedAuthority> authorities) {
        super(account.getMember().getEmail(), account.getPassword(), authorities);
        this.account = account;
    }
 
    public Account getAccount() {
        return account;
    }
 
    public Member getMember() {
        return account.getMember();
    }
}

AccountDetails имеет два дополнительных метода, которые позволяют получить доступ к связанной учетной записи и информации об участнике. AccountDetails затем используется нашей собственной реализацией UserDetailsService которая позднее используется диспетчером проверки подлинности DAO Spring Security для аутентификации пользователей.

Примечание. Настройка Spring Security выходит за рамки данной статьи.

2. Внедрение AccountDetails

Основное использование аннотации @AuthenticationPrincipal — это внедрение UserDetails. В нашем сценарии мы хотим, чтобы AccountDetails был введен. Для этого просто поместите аннотированный аргумент @AuthenticationPrincipal в метод обработчика Spring MVC:

1
2
3
4
@RequestMapping(value = {"", "/", "index.html"})
public String index(@AuthenticationPrincipal AccountDetails accountDetails) {
    return "index";
}

Если аутентифицированный пользователь не существует, accountDetails оценивается как null . В случае, если пользователь аутентифицирован — accountDetails оценивает действительный объект.

Примечание. Начиная с org.springframework.security.core.annotation.AuthenticationPrincipal Spring 4.0, вы должны использовать org.springframework.security.core.annotation.AuthenticationPrincipal

3. Использование expression для ввода свойств AccountDetails

AccountDetails есть два дополнительных метода — получить account и объекты- member . Если мы хотим внедрить их непосредственно в метод-обработчик, мы можем использовать свойство @AuthenticatedPricipal аннотации @AuthenticatedPricipal :

1
2
3
4
@RequestMapping(value = {"", "/", "index.html"})
public String index(@AuthenticationPrincipal(expression = "account") Account account) {
    return "index";
}
1
2
3
4
@RequestMapping(value = {"", "/", "index.html"})
public String index(@AuthenticationPrincipal(expression = "member") Member member) {
    return "index";
}

Выражение определяет выражение SpEL, которое будет использоваться при вставке аргумента. Довольно удобно.

4. Расширение аннотации @AuthenticationPrincipal

Вместо того, чтобы повторять методы обработчика @AuthenticationPrincipal(expression = "account") Account account мы можем создать @Controller и использовать ее в наших @Controller s:

1
2
3
4
5
6
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@AuthenticationPrincipal(expression = "account")
public @interface LoggedInAccount {
 
}

5. @AuthenticationPrincipal в Spring Security 3.2 и Spring Security 4+

  • Spring Security 3.2 — org.springframework.security.web.bind.annotation.AuthenticationPrincipal
  • Spring Security 4.0 — org.springframework.security.core.annotation.AuthenticationPrincipal