301

SpringSecurityを使用するSpringMVCWebアプリがあります。現在ログインしているユーザーのユーザー名を知りたい。以下に示すコードスニペットを使用しています。これは受け入れられた方法ですか?

このコントローラー内で静的メソッドを呼び出すのは好きではありません。これは、Springの目的全体であるIMHOを無効にします。代わりに、現在のSecurityContextまたは現在の認証が挿入されるようにアプリを構成する方法はありますか?

  @RequestMapping(method = RequestMethod.GET)
  public ModelAndView showResults(final HttpServletRequest request...) {
    final String currentUser = SecurityContextHolder.getContext().getAuthentication().getName();
    ...
  }
4

17 に答える 17

270

Spring 3を使用している場合、最も簡単な方法は次のとおりです。

 @RequestMapping(method = RequestMethod.GET)   
 public ModelAndView showResults(final HttpServletRequest request, Principal principal) {

     final String currentUser = principal.getName();

 }
于 2011-03-18T12:14:49.503 に答える
22

現在のユーザーの悪臭についてSecurityContextを照会する必要があることに同意します。これは、この問題を処理するための非常に非春の方法のようです。

この問題に対処するために、静的な「ヘルパー」クラスを作成しました。グローバルで静的なメソッドであるという点で汚いですが、セキュリティに関連するものを変更する場合は、少なくとも1か所で詳細を変更するだけでよいと考えました。

/**
* Returns the domain User object for the currently logged in user, or null
* if no User is logged in.
* 
* @return User object for the currently logged in user, or null if no User
*         is logged in.
*/
public static User getCurrentUser() {

    Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal()

    if (principal instanceof MyUserDetails) return ((MyUserDetails) principal).getUser();

    // principal object is either null or represents anonymous user -
    // neither of which our domain User object can represent - so return null
    return null;
}


/**
 * Utility method to determine if the current user is logged in /
 * authenticated.
 * <p>
 * Equivalent of calling:
 * <p>
 * <code>getCurrentUser() != null</code>
 * 
 * @return if user is logged in
 */
public static boolean isLoggedIn() {
    return getCurrentUser() != null;
}
于 2009-01-26T16:57:37.383 に答える
22

JSP ページに表示されるようにするには、Spring Security Tag Lib を使用できます。

http://static.springsource.org/spring-security/site/docs/3.0.x/reference/taglibs.html

タグを使用するには、JSP でセキュリティ taglib を宣言する必要があります。

<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>

次に、jsp ページで次のようにします。

<security:authorize access="isAuthenticated()">
    logged in as <security:authentication property="principal.username" /> 
</security:authorize>

<security:authorize access="! isAuthenticated()">
    not logged in
</security:authorize>

注: @SBerg413 のコメントで述べたように、追加する必要があります。

use-expressions="true"

これを機能させるには、security.xml 構成の「http」タグに追加します。

于 2012-03-18T23:58:04.707 に答える
13

HttpServletRequest.getUserPrincipal(); で認証済みユーザーを取得します。

例:

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.support.RequestContext;

import foo.Form;

@Controller
@RequestMapping(value="/welcome")
public class IndexController {

    @RequestMapping(method=RequestMethod.GET)
    public String getCreateForm(Model model, HttpServletRequest request) {

        if(request.getUserPrincipal() != null) {
            String loginName = request.getUserPrincipal().getName();
            System.out.println("loginName : " + loginName );
        }

        model.addAttribute("form", new Form());
        return "welcome";
    }
}
于 2010-07-08T03:34:38.653 に答える
10

Spring 3 以降では、次のオプションがあります。

オプション1 :

@RequestMapping(method = RequestMethod.GET)    
public String currentUserNameByPrincipal(Principal principal) {
    return principal.getName();
}

オプション 2 :

@RequestMapping(method = RequestMethod.GET)
public String currentUserNameByAuthentication(Authentication authentication) {
    return authentication.getName();
}

オプション 3:

@RequestMapping(method = RequestMethod.GET)    
public String currentUserByHTTPRequest(HttpServletRequest request) {
    return request.getUserPrincipal().getName();

}

オプション 4 : ファンシー :詳細については、こちらをご覧ください

public ModelAndView someRequestHandler(@ActiveUser User activeUser) {
  ...
}
于 2014-04-02T21:23:23.940 に答える
6

私はこれを行うだけです:

request.getRemoteUser();
于 2010-04-01T19:44:15.950 に答える
5

はい、静的は一般的に悪いです - 一般的に、しかしこの場合、静的はあなたが書くことができる最も安全なコードです. セキュリティ コンテキストはプリンシパルを現在実行中のスレッドに関連付けるため、最も安全なコードはスレッドから可能な限り直接的に静的にアクセスします。注入されたラッパー クラスの背後にアクセスを隠すことで、攻撃者はより多くの攻撃ポイントを得ることができます。コードにアクセスする必要はありません (jar が署名されている場合、コードを変更するのに苦労します)。構成をオーバーライドする方法が必要なだけです。これは、実行時に行うか、XML をクラスパスに挿入することができます。署名されたコードで注釈の挿入を使用しても、外部 XML でオーバーライドできます。このような XML は、実行中のシステムに不正なプリンシパルを挿入する可能性があります。

于 2010-02-04T13:03:56.047 に答える
4

私が書いた最後のSpring MVCアプリでは、SecurityContextホルダーを注入しませんでしたが、これに関連する2つのユーティリティメソッドを持つベースコントローラーがありました... isAuthenticated() & getUsername()。内部的には、説明した静的メソッド呼び出しを行います。

少なくとも、後でリファクタリングする必要がある場合は、一度だけです。

于 2008-10-30T23:08:59.380 に答える
4

Spring AOPアプローチを使用できます。たとえば、サービスがある場合、現在のプリンシパルを知る必要があります。カスタム アノテーション、つまり @Principal を導入できます。これは、この Service がプリンシパルに依存する必要があることを示します。

public class SomeService {
    private String principal;
    @Principal
    public setPrincipal(String principal){
        this.principal=principal;
    }
}

次に、MethodBeforeAdvice を拡張する必要があると思われるアドバイスで、特定のサービスに @Principal アノテーションがあることを確認し、プリンシパル名を挿入するか、代わりに「ANONYMOUS」に設定します。

于 2008-10-31T13:03:48.037 に答える
2

Spring 3 を使用していて、コントローラーで認証されたプリンシパルが必要な場合の最善の解決策は、次のようにすることです。

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;

    @Controller
    public class KnoteController {
        @RequestMapping(method = RequestMethod.GET)
        public java.lang.String list(Model uiModel, UsernamePasswordAuthenticationToken authToken) {

            if (authToken instanceof UsernamePasswordAuthenticationToken) {
                user = (User) authToken.getPrincipal();
            }
            ...

    }
于 2011-12-09T05:06:01.467 に答える
2

唯一の問題は、Spring Security で認証した後でも、ユーザー/プリンシパル Bean がコンテナーに存在しないため、依存性注入が困難になることです。Spring Security を使用する前に、現在のプリンシパルを持つセッション スコープの Bean を作成し、それを「AuthService」に注入してから、そのサービスをアプリケーション内の他のほとんどのサービスに注入していました。したがって、これらのサービスは単に authService.getCurrentUser() を呼び出してオブジェクトを取得します。セッションで同じプリンシパルへの参照を取得する場所がコード内にある場合は、それをセッション スコープ Bean のプロパティとして簡単に設定できます。

于 2008-11-29T07:41:18.860 に答える
1

これを試して

認証認証 = SecurityContextHolder.getContext().getAuthentication();
文字列 userName = authentication.getName();

于 2011-11-18T09:00:36.347 に答える
1

私は注釈付きのクラスだけでなく、クラスでも@AuthenticationPrincipal注釈を使用しています。元。:@Controller@ControllerAdvicer

@ControllerAdvice
public class ControllerAdvicer
{
    private static final Logger LOGGER = LoggerFactory.getLogger(ControllerAdvicer.class);


    @ModelAttribute("userActive")
    public UserActive currentUser(@AuthenticationPrincipal UserActive currentUser)
    {
        return currentUser;
    }
}

UserActiveログに記録されたユーザー サービスに使用するクラスはどこにあり、から拡張されorg.springframework.security.core.userdetails.Userます。何かのようなもの:

public class UserActive extends org.springframework.security.core.userdetails.User
{

    private final User user;

    public UserActive(User user)
    {
        super(user.getUsername(), user.getPasswordHash(), user.getGrantedAuthorities());
        this.user = user;
    }

     //More functions
}

本当に簡単です。

于 2015-07-30T23:40:27.670 に答える
1

コントローラーメソッドで依存関係として定義するPrincipalと、Spring は呼び出し時に現在の認証済みユーザーをメソッドに挿入します。

于 2015-11-10T11:29:11.713 に答える
-1

freemarker ページでユーザーの詳細をサポートする私の方法を共有したいと思います。すべてが非常にシンプルで、完璧に機能しています!

認証の再リクエストをdefault-target-url(フォームログイン後のページ)に配置するだけです。これは、そのページのコントローラーメソッドです。

@RequestMapping(value = "/monitoring", method = RequestMethod.GET)
public ModelAndView getMonitoringPage(Model model, final HttpServletRequest request) {
    showRequestLog("monitoring");


    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
    String userName = authentication.getName();
    //create a new session
    HttpSession session = request.getSession(true);
    session.setAttribute("username", userName);

    return new ModelAndView(catalogPath + "monitoring");
}

そして、これは私のftlコードです:

<@security.authorize ifAnyGranted="ROLE_ADMIN, ROLE_USER">
<p style="padding-right: 20px;">Logged in as ${username!"Anonymous" }</p>
</@security.authorize> 

以上で、ユーザー名は承認後にすべてのページに表示されます。

于 2013-06-29T15:35:05.813 に答える