Springセキュリティバージョン3.1.4.RELEASEを使用しています。現在ログインしているユーザーオブジェクトにアクセスするにはどうすればよいですか?
SecurityContextHolder.getContext().getAuthentication().getPrinciple()
ユーザーオブジェクトではなくユーザー名を返します。返されたユーザー名を使用してUserDetailsオブジェクトを取得するにはどうすればよいですか?
私は次のコードを試しました:
public UserDetails getLoggedInUser(){
final Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null && auth.isAuthenticated() && !(auth instanceof AnonymousAuthenticationToken))
{
if(auth.getDetails() !=null)
System.out.println(auth.getDetails().getClass());
if( auth.getDetails() instanceof UserDetails)
{
System.out.println("UserDetails");
}
else
{
System.out.println("!UserDetails");
}
}
return null;
}
結果は次のとおりです。
[2015-08-17 19:44:46.738] INFO http-bio-8443-exec-423 System.out class org.springframework.security.web.authentication.WebAuthenticationDetails
[2015-08-17 19:44:46.738] INFO http-bio-8443-exec-423 System.out !UserDetails
AuthenticationFilterクラスは次のとおりです。
public class CustomUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public static final String SPRING_SECURITY_FORM_USERNAME_KEY = "j_username";
public static final String SPRING_SECURITY_FORM_PASSWORD_KEY = "j_password";
public static final String SPRING_SECURITY_LAST_USERNAME_KEY = "SPRING_SECURITY_LAST_USERNAME";
private String usernameParameter = SPRING_SECURITY_FORM_USERNAME_KEY;
private String passwordParameter = SPRING_SECURITY_FORM_PASSWORD_KEY;
private boolean postOnly = true;
public CustomUsernamePasswordAuthenticationFilter() {
super("/j_spring_security_check");
}
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
if (postOnly && !request.getMethod().equals("POST")) {
throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
}
String username = obtainUsername(request);
String password = obtainPassword(request);
if (username == null) {
username = "";
}
if (password == null) {
password = "";
}
username = username.trim();
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
// Allow subclasses to set the "details" property
setDetails(request, authRequest);
if(this.getAuthenticationManager()==null){
logger.info("Authentication manager is null.");
} else {
logger.info("Authentication manager was "+this.getAuthenticationManager().getClass().getName());
}
return this.getAuthenticationManager().authenticate(authRequest);
}
protected String obtainPassword(HttpServletRequest request) {
return request.getParameter(passwordParameter);
}
protected String obtainUsername(HttpServletRequest request) {
return request.getParameter(usernameParameter);
}
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
}
public void setUsernameParameter(String usernameParameter) {
this.usernameParameter = usernameParameter;
}
public void setPasswordParameter(String passwordParameter) {
this.passwordParameter = passwordParameter;
}
public void setPostOnly(boolean postOnly) {
this.postOnly = postOnly;
}
public final String getUsernameParameter() {
return usernameParameter;
}
public final String getPasswordParameter() {
return passwordParameter;
}
}
AuthenticationProviderは次のとおりです。
@Component
public class CustomAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
private MyUserDetailsService userDetailsService;
public MyUserDetailsService getUserDetailsService() {
return userDetailsService;
}
public void setUserDetailsService(MyUserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
@Override
protected void additionalAuthenticationChecks(UserDetails arg0,
UsernamePasswordAuthenticationToken arg1)
throws AuthenticationException {
}
@Override
protected UserDetails retrieveUser(String arg0,
UsernamePasswordAuthenticationToken arg1)
throws AuthenticationException {
return userDetailsService.loadUserByUsername(arg0);
}
}
次のようなUserDetailsクラス:
public class MyUserDetailsService implements UserDetailsService {
private final Map<String, UserDetails> usersList;
public MyUserDetailsService() {
Collection<GrantedAuthority> authorityList;
final SimpleGrantedAuthority supervisorAuthority = new SimpleGrantedAuthority("supervisor");
final SimpleGrantedAuthority userAuthority = new SimpleGrantedAuthority("user");
usersList = new TreeMap<String, UserDetails>();
authorityList = new ArrayList<GrantedAuthority>();
authorityList.add(supervisorAuthority);
authorityList.add(userAuthority);
usersList.put("admin", new User("admin", "admin", authorityList));
authorityList = new ArrayList<GrantedAuthority>();
authorityList.add(userAuthority);
usersList.put("peter", new User("peter", "password123", authorityList));
//probably don't use this in production
for(Map.Entry<String, UserDetails> user : usersList.entrySet()){
logger.info(user.getValue().toString());
}
}
@Override
public UserDetails loadUserByUsername(String username)throws UsernameNotFoundException {
UserDetails ud = usersList.get(username);
if (ud != null) {
logger.info("loadUserByUsername: found match, returning "
+ ud.getUsername() + ":" + ud.getPassword() + ":"
+ ud.getAuthorities().toString());
return new User(ud.getUsername(), ud.getPassword(),
ud.getAuthorities());
}
logger.info("loadUserByUsername: did not find match, throwing UsernameNotFoundException");
throw new UsernameNotFoundException(username);
}
}
SecurityContextHolder.getContext().getAuthentication().getPrincipal();
現在のユーザーオブジェクトを返します。これは、User
、UserDetails
、またはカスタムユーザーオブジェクトです。戻りオブジェクトをUserDetails
にキャストするか、カスタムオブジェクトの場合は独自のユーザーオブジェクトにキャストする必要があります。
または、Authentication
またはPrincipal
をコントローラーに直接注入できます。原則はUserDetails
/customユーザーオブジェクトです。
注:UserDetails
はインターフェースです
次のように使用できます
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
String username = ((UserDetails)principal).getUsername();
} else {
String username = principal.toString();
}
それは春のセキュリティリファレンスにあります http://docs.spring.io/spring-security/site/docs/4.0.2.RELEASE/reference/htmlsingle/#obtaining-information-about-the-current-user
あなたはただ一歩先に進みました。 SecurityContextHolder.getContext().getAuthentication()
はAuthentication
オブジェクトを返します。 Yoは、ユーザーをどのように認証したか、およびAuthentication
を実装する具象クラスは何を知っている必要があります。それがAbstractAuthenticationToken
のサブクラスであり(Springが提供するすべての実装がそうである)、getDetails()
がUserDetails
を返すと仮定すると、単に使用できます:
AbstractAuthenticationToken auth = (AbstractAuthenticationToken)
SecurityContextHolder.getContext().getAuthentication();
UserDetails details = (UserDetails) auth.getDetails();
次のように、認証インターフェイスをコントローラーに挿入するだけで、ログインしているユーザーのユーザー名を取得できます。
@Controller
public class SomeController {
@GetMapping(value = "/username")
@ResponseBody
public String currentUserName(Authentication authentication) {
if (authentication != null) {
return authentication.getName();
} else {
return "";
}
}
}