স্প্রিং সিকিউরিটি ব্যবহার করার সময়, শিমের বর্তমান ব্যবহারকারীর নাম (যেমন সিকিউরিটি কনটেক্সট) তথ্য পাওয়ার সঠিক উপায় কী?


288

আমার কাছে একটি স্প্রিং এমভিসি ওয়েব অ্যাপ্লিকেশন রয়েছে যা স্প্রিং সুরক্ষা ব্যবহার করে। আমি বর্তমানে লগ ইন করা ব্যবহারকারীর নাম জানতে চাই। আমি নীচে দেওয়া কোড স্নিপেট ব্যবহার করছি। এটি কি গ্রহণযোগ্য উপায়?

আমি এই নিয়ামকের অভ্যন্তরে স্থির পদ্ধতিতে কল করতে পছন্দ করি না - যা স্প্রিংয়ের পুরো উদ্দেশ্যকে হারাতে পারে, আইএমএইচও। এর পরিবর্তে বর্তমান সিকিউরিটি কনটেক্সট বা বর্তমান প্রমাণীকরণের জন্য অ্যাপটি কনফিগার করার কোনও উপায় আছে কি?

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

সুপার ক্লাস হিসাবে আপনার কাছে কোনও কন্ট্রোলার (সুরক্ষিত নিয়ামক) নেই কেন সিকিউরিটি কনটেক্সট থেকে ব্যবহারকারী পান এবং সেটিকে শ্রেণীর অভ্যন্তরে উদাহরণ পরিবর্তনযোগ্য হিসাবে সেট করেন? আপনি যখন সুরক্ষিত নিয়ামককে প্রসারিত করেন, তখন আপনার পুরো বর্গের বর্তমান প্রসঙ্গে ব্যবহারকারী প্রিন্সিপালের অ্যাক্সেস থাকবে।
দেহান ডি ক্রুস

উত্তর:


259

আপনি যদি স্প্রিং 3 ব্যবহার করেন তবে সবচেয়ে সহজ উপায় হ'ল:

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

     final String currentUser = principal.getName();

 }

69

এই প্রশ্নের উত্তর দেওয়া হওয়ার পরে বসন্ত বিশ্বে অনেক কিছুই পরিবর্তিত হয়েছে। স্প্রিং বর্তমান ব্যবহারকারীকে একটি নিয়ামক হিসাবে পাওয়া সহজ করেছে। অন্যান্য মটরশুটির জন্য, বসন্ত লেখকের পরামর্শ গ্রহণ করেছে এবং 'সিকিউরিটি কনটেক্সটহোল্ডার' এর ইনজেকশনটিকে সহজ করেছে। আরও বিস্তারিত মন্তব্য করা হয়।


এই সমাধানটি আমি শেষ করে শেষ করেছি। SecurityContextHolderআমার নিয়ামকটি ব্যবহার করার পরিবর্তে , আমি এমন কিছু ইনজেকশান করতে চাই যা SecurityContextHolderহুডের নীচে ব্যবহার করে তবে আমার কোড থেকে সেই সিঙ্গলটন-জাতীয় ক্লাসটি বিমূর্ত করে দেয়। আমার নিজের ইন্টারফেসটি ঘুরিয়ে দেওয়া ছাড়া এটি করার কোনও উপায় আমি খুঁজে পাইনি:

public interface SecurityContextFacade {

  SecurityContext getContext();

  void setContext(SecurityContext securityContext);

}

এখন, আমার নিয়ামক (বা যাই হোক POJO) এর মতো দেখতে পাবেন:

public class FooController {

  private final SecurityContextFacade securityContextFacade;

  public FooController(SecurityContextFacade securityContextFacade) {
    this.securityContextFacade = securityContextFacade;
  }

  public void doSomething(){
    SecurityContext context = securityContextFacade.getContext();
    // do something w/ context
  }

}

এবং, ইন্টারফেসটি ডিউপলিংয়ের বিন্দু হওয়ার কারণে, ইউনিট পরীক্ষাটি সোজা। এই উদাহরণে আমি মকিতো ব্যবহার করি:

public class FooControllerTest {

  private FooController controller;
  private SecurityContextFacade mockSecurityContextFacade;
  private SecurityContext mockSecurityContext;

  @Before
  public void setUp() throws Exception {
    mockSecurityContextFacade = mock(SecurityContextFacade.class);
    mockSecurityContext = mock(SecurityContext.class);
    stub(mockSecurityContextFacade.getContext()).toReturn(mockSecurityContext);
    controller = new FooController(mockSecurityContextFacade);
  }

  @Test
  public void testDoSomething() {
    controller.doSomething();
    verify(mockSecurityContextFacade).getContext();
  }

}

ইন্টারফেসের ডিফল্ট বাস্তবায়নটি এরকম দেখাচ্ছে:

public class SecurityContextHolderFacade implements SecurityContextFacade {

  public SecurityContext getContext() {
    return SecurityContextHolder.getContext();
  }

  public void setContext(SecurityContext securityContext) {
    SecurityContextHolder.setContext(securityContext);
  }

}

এবং, অবশেষে, উত্পাদনের স্প্রিং কনফিগারেশনটি এর মতো দেখাচ্ছে:

<bean id="myController" class="com.foo.FooController">
     ...
  <constructor-arg index="1">
    <bean class="com.foo.SecurityContextHolderFacade">
  </constructor-arg>
</bean>

কিছুটা নির্বোধের চেয়ে আরও বেশি মনে হয় যে স্প্রিং, সমস্ত জিনিসের নির্ভরতা ইনজেকশন ধারক, অনুরূপ কিছু ইনজেকশনের কোনও উপায় সরবরাহ করে নি। আমি বুঝতে পারি যে SecurityContextHolderএসিজি থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হয়েছিল, তবে এখনও। বিষয়টি হ'ল এগুলি এতটা কাছাকাছি - SecurityContextHolderঅন্তর্নিহিত SecurityContextHolderStrategyউদাহরণটি (যা একটি ইন্টারফেস) পাওয়ার জন্য যদি কেবল কোনও গেট থাকে তবে আপনি এটি ইনজেকশন করতে পারতেন। আসলে, আমি এমনকি জের ইস্যুটি খোলার জন্য।

একটি শেষ কথা - আমি এখানে আগে আমার দেওয়া উত্তরটি যথেষ্ট পরিমাণে পরিবর্তন করেছি। আপনি যদি কৌতূহলী হন তবে ইতিহাসটি যাচাই করুন তবে সহকর্মী যেমন আমাকে বলেছিলেন, আমার আগের উত্তরটি বহু-থ্রেডযুক্ত পরিবেশে কাজ করবে না। অন্তর্নিহিত SecurityContextHolderStrategyব্যবহৃত SecurityContextHolderহয়, ডিফল্টরূপে, এর একটি উদাহরণ ThreadLocalSecurityContextHolderStrategy, যা SecurityContextএস এ সঞ্চয় করে ThreadLocal। সুতরাং, SecurityContextআরম্ভের সময় সরাসরি শিমের মধ্যে সরাসরি ইনজেক্ট করা ভাল ধারণা নয় - এটি ThreadLocalপ্রতিটি সময় থেকে বহু-থ্রেডযুক্ত পরিবেশে পুনরুদ্ধার করা প্রয়োজন, তাই সঠিকটি পুনরুদ্ধার করা হবে।


1
আমি আপনার সমাধানটি পছন্দ করি - এটি বসন্তের ফ্যাক্টরি-পদ্ধতি সহায়তার একটি চতুর ব্যবহার। এটি বলেছিল, এটি আপনার পক্ষে কাজ করছে কারণ নিয়ামক বস্তুটি ওয়েব অনুরোধে যায়। আপনি যদি নিয়ন্ত্রকের শিমের ক্ষেত্রটি ভুল উপায়ে পরিবর্তন করেন তবে এটি ভঙ্গ হবে।
পল মরি

2
পূর্ববর্তী দুটি মন্তব্য একটি পুরানো, ভুল উত্তর উল্লেখ করে যা আমি সবেমাত্র প্রতিস্থাপন করেছি।
স্কট বেল

12
এটি কি বর্তমান বসন্ত রিলিজের সাথে প্রস্তাবিত সমাধান? আমি বিশ্বাস করতে পারি না যে কেবলমাত্র ব্যবহারকারীর নামটি পুনরুদ্ধার করতে এর এত বেশি কোড দরকার needs
টা সাস

6
যদি আপনি স্প্রিং সিকিউরিটি ..০.x ব্যবহার করেন তবে তারা আমার পরামর্শটি JIRA ইস্যুতে বাস্তবায়িত করেছে আমি jira.springsource.org/browse/SEC-1188 লগড করেছি যাতে আপনি এখন সিকিউরিটি কনটেক্সটহোল্ডারস্ট্রেজি উদাহরণটি (সিকিউরিটি কনটেক্সটহোল্ডার থেকে) ইনজেক্ট করতে পারেন স্ট্যান্ডার্ডের মাধ্যমে সরাসরি আপনার শিমের মধ্যে ject বসন্ত কনফিগারেশন।
স্কট বেল

4
সুনাদে 21 উত্তর দেখুন। স্প্রিং 3 আপনাকে এখন জাভা.সিকিউরিটি ব্যবহার করার অনুমতি দেয় rআপনার নিয়ন্ত্রকটিতে একটি মূল তর্ক হিসাবে প্রিন্সিপাল
প্যাট্রিক

22

আমি সম্মত হই যে বর্তমান ব্যবহারকারীর দুর্ঘটনার জন্য সিকিউরিটি কনটেক্সটকে জিজ্ঞাসা করা, এই সমস্যাটি হ্যান্ডেল করার জন্য এটি একটি খুব অ-বসন্ত উপায় বলে মনে হচ্ছে।

এই সমস্যাটি মোকাবেলায় আমি একটি স্থিতিশীল "সহায়ক" শ্রেণি লিখেছি; এটি নোংরা যে এটি একটি বৈশ্বিক এবং স্থিতিশীল পদ্ধতি, তবে আমি সুরক্ষা সম্পর্কিত কোনও কিছু পরিবর্তন করতে পারলে আমি এইভাবে অনুভব করেছি, কমপক্ষে আমাকে কেবলমাত্র এক জায়গায় বিশদটি পরিবর্তন করতে হবে:

/**
* 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;
}

22
এটি সিকিউরিটি কনটেক্সটহোল্ডার.জেটকন্টেক্সট () হিসাবে দীর্ঘ হয় এবং পরেরটি থ্রেডসফ থাকে যেহেতু এটি সুরক্ষা বিশদটিকে থ্রেডলকেলে রাখে। এই কোডটি কোনও রাজ্য বজায় রাখে না।
ম্যাট বি

22

এটি কেবল আপনার জেএসপি পৃষ্ঠাগুলিতে প্রদর্শিত হতে আপনি স্প্রিং সুরক্ষা ট্যাগ লিব ব্যবহার করতে পারেন:

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

যে কোনও ট্যাগ ব্যবহার করার জন্য, আপনাকে অবশ্যই আপনার জেএসপিতে সুরক্ষা ট্যাগলিব ঘোষণা করতে হবে:

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

তারপরে একটি জেএসপি পৃষ্ঠায় এমন কিছু করুন:

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

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

দ্রষ্টব্য: @ SBerg413 এর মন্তব্যে যেমন উল্লেখ করা হয়েছে, আপনাকে যুক্ত করতে হবে

ব্যবহার-এক্সপ্রেশন = "সত্য"

এটি কাজ করার জন্য সুরক্ষা.এক্সএমএল কনফিগারেশনে "http" ট্যাগটিতে।


দেখে মনে হচ্ছে এটি সম্ভবত বসন্ত সুরক্ষা-অনুমোদিত উপায়!
নিক স্পেস্ক

3
এই পদ্ধতিটি কাজ করার জন্য, আপনাকে সুরক্ষা.এক্সএমএল কনফিগারেশনে http ট্যাগটিতে ব্যবহার-এক্সপ্রেশন = "সত্য" যুক্ত করতে হবে।
এসবার্গ 413

ধন্যবাদ @ এসবার্গ ৪৪১, আমি আমার উত্তরটি সম্পাদনা করব এবং আপনার গুরুত্বপূর্ণ ব্যাখ্যা যুক্ত করব!
ব্র্যাড পার্কস

14

আপনি যদি স্প্রিং সিকিউরিটি ver> = 3.2 ব্যবহার করেন তবে আপনি @AuthenticationPrincipalটিকাটি ব্যবহার করতে পারেন :

@RequestMapping(method = RequestMethod.GET)
public ModelAndView showResults(@AuthenticationPrincipal CustomUser currentUser, HttpServletRequest request) {
    String currentUsername = currentUser.getUsername();
    // ...
}

এখানে, CustomUserএকটি কাস্টম অবজেক্ট যা প্রয়োগ করে UserDetailsযা কাস্টমস দ্বারা ফিরে আসে UserDetailsService

আরও তথ্য স্প্রিং সিকিউরিটি রেফারেন্স ডক্সের @ প্রমাণীকরণের মূল নীতিমালায় পাওয়া যাবে can


13

আমি HTTPServletRequest.getUserPr originalal () দ্বারা অনুমোদনপ্রাপ্ত ব্যবহারকারী পেয়েছি;

উদাহরণ:

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";
    }
}

আমি আপনার সমাধান পছন্দ। স্প্রিং বিশেষজ্ঞদের কাছে: এটি কি নিরাপদ, ভাল সমাধান?
মারিওশ

ভাল সমাধান নয়। nullব্যবহারকারীর বেনামে ( http> anonymousস্প্রিং সিকিউরিটি এক্সএমএল এর উপাদানগুলি) প্রমাণীকরণ করা হলে আপনি পাবেন । SecurityContextHolderবা SecurityContextHolderStrategyসঠিক উপায়।
এখনকার

1
যাতে আমি যাচাই করে ফেলেছি যদি নাল রিকুয়েস্ট না হয়। বিট ইউজারপ্রিন্সিপাল ()! = নাল
digz6666

ফিল্টারে নাল হয়
অ্যালেক্স 78191

9

স্প্রিং 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) {
  ...
}

1
৩.২ থেকে, বসন্ত-সুরক্ষা-ওয়েব আসে @CurrentUserযা @ActiveUserআপনার লিঙ্ক থেকে কাস্টমটির মতো কাজ করে ।
মাইক পার্টরিজ

@ মাইকপার্টরিজ, আপনি কি বলছেন, কোনও লিঙ্ক খুঁজে পাবে না বলে মনে হচ্ছে ?? বা আরও তথ্য ??
আজেফেরতি

1
আমার ভুল - আমি স্প্রিং সুরক্ষা প্রমাণীকরণের প্রিন্সিপালআরগমেন্ট রিসোলভার জাভাদোককে ভুল বুঝি। @AuthenticationPrincipalকাস্টম @CurrentUserটীকা দিয়ে মোড়ানো সেখানে একটি উদাহরণ দেখানো হয়েছে । ৩.২ থেকে লিঙ্কিত উত্তরের মতো আমাদের কোনও কাস্টম আর্গুমেন্ট রিসলভার কার্যকর করার দরকার নেই। এই অন্যান্য উত্তরে আরও বিশদ রয়েছে।
মাইক পার্ট্রিজে

5

হ্যাঁ, স্ট্যাটিকস সাধারণত খারাপ থাকে - সাধারণত, তবে এই ক্ষেত্রে স্ট্যাটিকটি আপনি লিখতে পারেন এমন সবচেয়ে সুরক্ষিত কোড। যেহেতু সুরক্ষা প্রসঙ্গটি বর্তমানে চলমান থ্রেডের সাথে কোনও অধ্যক্ষকে সংযুক্ত করে, তাই সর্বাধিক সুরক্ষিত কোড থ্রেড থেকে যথাসম্ভব সরাসরি স্থিতি অ্যাক্সেস করতে পারে। ইনজেকশন দেওয়া একটি মোড়কের ক্লাসের পিছনে অ্যাক্সেস লুকিয়ে রাখলে আক্রমণকারীকে আক্রমণ করার আরও বেশি পয়েন্ট সরবরাহ করা হয়। তাদের কোডটিতে অ্যাক্সেসের প্রয়োজন হবে না (যা জারে স্বাক্ষরিত হলে তাদের পরিবর্তন করতে খুব অসুবিধা হবে), তাদের কেবলমাত্র কনফিগারেশনটি ওভাররাইড করার জন্য একটি উপায় প্রয়োজন যা রানটাইম বা ক্লাসপথে কিছু এক্সএমএল পিছলে যেতে পারে। এমনকি স্বাক্ষরিত কোডটিতে টীকাগুলি ইনজেকশন ব্যবহার করা বাহ্যিক এক্সএমএল এর সাথে ওভাররেডযোগ্য হবে। এই জাতীয় এক্সএমএল একটি দুর্বৃত্ত অধ্যক্ষের সাথে চলমান সিস্টেমকে ইনজেক্ট করতে পারে।


5

আমি কেবল এটি করব:

request.getRemoteUser();

1
এটি কার্যকর হতে পারে, তবে নির্ভরযোগ্যভাবে নয়। জাভাডোক থেকে: "প্রতিটি পরবর্তী অনুরোধের সাথে ব্যবহারকারীর নাম প্রেরণ করা হয় কিনা তা ব্রাউজার এবং প্রমাণীকরণের ধরণের উপর নির্ভর করে" " - download-llnw.oracle.com/javaee/6/api/javax/servlet/http/...
স্কট বেল

3
স্প্রিং সিকিউরিটি ওয়েব অ্যাপ্লিকেশনে রিমোট ইউজারনেম পাওয়ার জন্য এটি আসলে একটি বৈধ এবং খুব সহজ উপায়। স্ট্যান্ডার্ড ফিল্টার চেইনে একটি অন্তর্ভুক্ত রয়েছে SecurityContextHolderAwareRequestFilterযা অনুরোধটি মোড় করে এবং অ্যাক্সেসের মাধ্যমে এই কলটি প্রয়োগ করে SecurityContextHolder
ভেড়া ভেড়া

4

সর্বশেষ স্প্রিং এমভিসি অ্যাপ্লিকেশনের জন্য আমি লিখেছিলাম, আমি সিকিউরিটি কনটেক্সট ধারককে ইনজেকশন দিইনি, তবে আমার কাছে বেস কন্ট্রোলার ছিল যে আমার ... এর সাথে সম্পর্কিত দুটি ইউটিলিটি পদ্ধতি ছিল isআসটিকেশন () এবং getUsername ()। অভ্যন্তরীণভাবে তারা আপনার বর্ণিত স্থিতির পদ্ধতি কল করে।

আপনার যদি পরে রিফ্যাক্টরের প্রয়োজন হয় তবে কমপক্ষে তবে এটি একবারে রয়েছে।


3

আপনি স্প্রিং এওপি অ্যাপ্রোচ ব্যবহার করতে পারেন। উদাহরণস্বরূপ আপনার যদি কিছু পরিষেবা থাকে তবে তার জন্য বর্তমান অধ্যক্ষকে জানতে হবে। আপনি কাস্টম টীকা যেমন @ প্রিন্সিপাল প্রবর্তন করতে পারেন, যা নির্দেশ করে যে এই পরিষেবাটি প্রধান নির্ভরশীল হওয়া উচিত।

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

তারপরে আপনার পরামর্শ অনুসারে, যা আমি মনে করি মেথডোফেরএনডভাইসকে প্রসারিত করা দরকার, সেই নির্দিষ্ট পরিষেবাটিতে @ প্রিন্সিপাল টিকা আছে এবং প্রধান নামটি ইনজেকশন করা আছে, বা এটি পরিবর্তে 'অ্যানওয়াইমাস' এ সেট করুন।


আমাকে পরিষেবা ক্লাসের ভিতরে অধ্যক্ষের অ্যাক্সেস করতে হবে আপনি কি গিথুবে একটি সম্পূর্ণ উদাহরণ পোস্ট করতে পারেন? আমি স্প্রিং এওপি জানি না, অতএব অনুরোধ।
রাকেশ ওয়াঘেলা

2

একমাত্র সমস্যাটি হ'ল স্প্রিং সিকিউরিটির সাথে প্রমাণীকরণ করার পরেও, ধারকটিতে ব্যবহারকারীর / প্রধান শিমের অস্তিত্ব নেই, সুতরাং নির্ভরতা-ইনজেকশন এটি কঠিন হবে। স্প্রিং সিকিউরিটি ব্যবহার করার আগে আমরা একটি সেশন-স্কোপড শিম তৈরি করতাম যার বর্তমান প্রিন্সিপাল ছিল, এটি "আথ সার্ভিস" ইনজেক্ট করুন এবং তারপরে অ্যাপ্লিকেশনটির বেশিরভাগ পরিষেবাগুলিতে সেই পরিষেবাটি ইনজেক্ট করুন। সুতরাং সেই পরিষেবাগুলি অবজেক্টটি পেতে সহজভাবে authService.getCurrentUser () কল করবে। আপনার কোডে যদি এমন কোনও জায়গা থাকে যেখানে আপনি সেশনে একই অধ্যক্ষের একটি রেফারেন্স পান তবে আপনি কেবল এটিকে আপনার সেশন-স্কোপড বিনের সম্পত্তি হিসাবে সেট করতে পারেন।


1

এটা চেষ্টা কর

প্রমাণীকরণ প্রমাণীকরণ = সিকিউরিটি কনটেক্সটহোল্ডার.সেটকন্টেক্সট ()। GetAuthentication ();
স্ট্রিং ইউজারনেম = প্রমাণীকরণ.গেটনাম ();


3
সিকিউরিটি কনটেক্সটহোল্ডার.জেটকন্টেক্সট () স্থিতিশীল পদ্ধতিটি কল করা হ'ল মূল প্রশ্নের মধ্যে আমি যা অভিযোগ করছিলাম। আপনি কোন উত্তর দেয় নি।
স্কট বেল

2
এটি অবশ্য ডকুমেন্টেশনের সুপারিশ অনুসারে ঠিক: স্ট্যাটিক.স্প্রিংসোর্স.আর / স্প্রিং-সিকিউরিটি / সাইট / ডকস / ৩.০.x/… তাই আপনি এড়িয়ে কী সম্পাদন করছেন? আপনি একটি সাধারণ সমস্যার জটিল সমাধান খুঁজছেন। সর্বোপরি - আপনি একই আচরণ পান। সবচেয়ে খারাপ সময়ে, আপনি একটি বাগ বা সুরক্ষা গর্ত পাবেন।
বব কার্নস

2
@ BobKerns পরীক্ষার জন্য, স্থানীয় থ্রেডে রাখার বিপরীতে প্রমাণীকরণটি ইনজেকশনে সক্ষম হওয়া আরও পরিষ্কার।

1

আপনি যদি স্প্রিং 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();
            }
            ...

    }

1
যখন প্যারামিটারটি ইতিমধ্যে ব্যবহারকারীর নামপাসওয়ার্ডআউটেন্টিফিকেশন টোকেন টাইপ করা হয় তখন আপনি কেন এই ব্যবহারকারীর নাম পাসওয়ার্ডআউটেন্টিফিকেশন টোকেন চেক করেন?
স্কট বেল

(authToken উদাহরণস্বরূপ ব্যবহারকারীর নামপাসওয়ার্ডআউটেন্টিফিকেশন টোকেন) যদি (authToken! = নাল) এর কার্যকরী সমতুল্য। দ্বিতীয়টি খুব পরিষ্কার হতে পারে তবে অন্যথায় কোনও পার্থক্য নেই।
চিহ্নিত করুন

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
}

সত্যিই সহজ।


0

Principalআপনার নিয়ামক পদ্ধতিতে নির্ভরতা হিসাবে সংজ্ঞা দিন এবং বসন্তটি আপনার পদ্ধতিতে বর্তমান অনুমোদনপ্রাপ্ত ব্যবহারকারীকে অনুরোধের সময় ইনজেকশন দেবে।


-2

আমি ফ্রিমার্কার পৃষ্ঠায় ব্যবহারকারীর বিবরণ সমর্থন করার আমার উপায় ভাগ করতে চাই। সবকিছু খুব সহজ এবং নিখুঁতভাবে কাজ করছে!

আপনাকে কেবলমাত্র প্রমাণীকরণের পুনঃনির্ধারণটি 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");
}

এবং এটি আমার এফটিএল কোড:

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

এবং এটি হ'ল অনুমোদনের পরে প্রতিটি পৃষ্ঠায় ব্যবহারকারীর নাম উপস্থিত হবে।


উত্তর দেওয়ার চেষ্টা করার জন্য ধন্যবাদ, তবে স্থির পদ্ধতি সিকিউরিটি কনটেক্সটহোল্ডার.সেটকন্টেক্সট () এর ব্যবহারটি হ'ল আমি এড়াতে চাইছিলাম এবং যে কারণে আমি এই প্রশ্নটি প্রথম স্থানে জিজ্ঞাসা করেছি।
স্কট বেল
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.