স্প্রিং সিকিউরিটি সহ জাভা কোডে "হাস্যরোল" কীভাবে চেক করবেন?


118

জাভা কোডে ব্যবহারকারী কর্তৃপক্ষ বা অনুমতি কীভাবে চেক করবেন? উদাহরণস্বরূপ - আমি ভূমিকার উপর নির্ভর করে ব্যবহারকারীর জন্য বোতামটি প্রদর্শন করতে বা প্রদর্শন করতে চাই। এখানে টীকা রয়েছে:

@PreAuthorize("hasRole('ROLE_USER')")

এটি জাভা কোডে কীভাবে তৈরি করবেন? কিছুটা এইরকম :

if(somethingHere.hasRole("ROLE_MANAGER")) {
   layout.addComponent(new Button("Edit users"));
}

উত্তর:


70

স্প্রিং সিকিউরিটি 3.0 এর এপিআই রয়েছে

SecurityContextHolderAwareRequestWrapper.isUserInRole(String role)

আপনি রাবারটি ব্যবহারের আগে আপনাকে ইনজেক্ট করতে হবে।

SecurityContextHolderAwareRequestWrapper


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

3
আমি কীভাবে নিয়ন্ত্রণকারীর মোড়কটি পুনরুদ্ধার করতে পারি?
আলফোনসো টাইন্দা

3
আমি কীভাবে সিকিউরিটি কনটেক্সটহোল্ডারআওয়ারেরউইকুয়েস্ট্রাপারের উদাহরণ পেতে পারি?
gstackoverflow

2
এক্সট্রিম বাইকার ঠিক আছে, আপনি সিকিউরিটি কনটেক্সটহোল্ডারআওয়ারেকুয়েস্টওয়্যার ক্লাসটি কীভাবে পাবেন? এটি কোনও স্থির বস্তু নয়।
এটি

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

144

আপনি HTTPServletRequest অবজেক্টের isUserInRole পদ্ধতি ব্যবহার করতে পারেন।

কিছুটা এইরকম:

public String createForm(HttpSession session, HttpServletRequest request,  ModelMap   modelMap) {


    if (request.isUserInRole("ROLE_ADMIN")) {
        // code here
    }
}

আমার মনে হয় পরীক্ষা করা সহজ
ফেগো

1
তবে আমি যদি অনুরোধ না করি?
gstackoverflow

((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest()অনুরোধ পেতে কি ? :)
পেটর zjezdský

4
@ অ্যাটওয়ার্ড এইচটিটিপি সার্ভেলকুইয়েস্ট অনুরোধ; ?
পাসকাল

এবং এটি এমনকি একটি স্প্রিং এপিআইও নয়, সরল সার্লেট স্পেক! একটি লজ্জা যা নির্বাচিত উত্তর নয়
গ্রেগফ্যাক্ট

67

ইউজারডেটেল থেকে কর্তৃত্ব সন্ধান করতে একটি লুপ ব্যবহার না করে আপনি এটি করতে পারেন:

Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
boolean authorized = authorities.contains(new SimpleGrantedAuthority("ROLE_ADMIN"));

2
খুব ভাল উত্তর, তবে ROLE_ADMIN ডাবল উক্তি হওয়া উচিত।
এরিকা কেন

6
এটি খুব ঝুঁকিপূর্ণ। সচেতন থাকুন যে গ্রান্টডঅর্থারিটি বাস্তবায়নের আরেকটি বাস্তবায়নে স্যুইচ করা (উদাহরণস্বরূপ জেএএএস, অন্য অনুমোদনের সম্ভাবনা যুক্ত করে) এই কোডটিকে ত্রুটিযুক্ত করবে। সিম্পলগ্রান্টেড অথরিটিটিতে সমান () বাস্তবায়ন দেখুন
পেটর zjezdský

47

আপনি সুরক্ষা প্রসঙ্গে পুনরুদ্ধার করতে পারেন এবং তারপরে এটি ব্যবহার করতে পারেন:

    import org.springframework.security.core.Authentication;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.context.SecurityContext;
    import org.springframework.security.core.context.SecurityContextHolder;

    protected boolean hasRole(String role) {
        // get security context from thread local
        SecurityContext context = SecurityContextHolder.getContext();
        if (context == null)
            return false;

        Authentication authentication = context.getAuthentication();
        if (authentication == null)
            return false;

        for (GrantedAuthority auth : authentication.getAuthorities()) {
            if (role.equals(auth.getAuthority()))
                return true;
        }

        return false;
    }

SecurityContextHolder.getContext()কখনই নয় NULL, ডক্স পরীক্ষা করুন। সুতরাং আপনি প্রসঙ্গ সন্ধান করা এড়াতে পারেন NULL
ইমতিয়াজ শাকিল সিদ্দিক

14

আপনি নীচে হিসাবে একটি হ্যাসরোল () পদ্ধতি প্রয়োগ করতে পারেন - (এটি অন্যান্য সংস্করণ সম্পর্কে নিশ্চিত না স্প্রিং সুরক্ষা 3.0.x এ পরীক্ষা করা হয়))

  protected final boolean hasRole(String role) {
    boolean hasRole = false;
    UserDetails userDetails = getUserDetails();
    if (userDetails != null) {
      Collection<GrantedAuthority> authorities = userDetails.getAuthorities();
      if (isRolePresent(authorities, role)) {
        hasRole = true;
      }
    } 
    return hasRole;
  }
  /**
   * Get info about currently logged in user
   * @return UserDetails if found in the context, null otherwise
   */
  protected UserDetails getUserDetails() {
    Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    UserDetails userDetails = null;
    if (principal instanceof UserDetails) {
      userDetails = (UserDetails) principal;
    }
    return userDetails;
  }
  /**
   * Check if a role is present in the authorities of current user
   * @param authorities all authorities assigned to current user
   * @param role required authority
   * @return true if role is present in list of authorities assigned to current user, false otherwise
   */
  private boolean isRolePresent(Collection<GrantedAuthority> authorities, String role) {
    boolean isRolePresent = false;
    for (GrantedAuthority grantedAuthority : authorities) {
      isRolePresent = grantedAuthority.getAuthority().equals(role);
      if (isRolePresent) break;
    }
    return isRolePresent;
  }

1
SecurityContextHolder.getContext().getAuthentication()পুনরুদ্ধার করতে পারেন null। আপনি কিছু চেক যোগ করতে পারেন?
মিস্টারফুল

10

আমি এটি ব্যবহার করছি:

@RequestMapping(method = RequestMethod.GET)
public void welcome(SecurityContextHolderAwareRequestWrapper request) {
    boolean b = request.isUserInRole("ROLE_ADMIN");
    System.out.println("ROLE_ADMIN=" + b);

    boolean c = request.isUserInRole("ROLE_USER");
    System.out.println("ROLE_USER=" + c);
}

8

আপনি কর্তৃপক্ষের ক্লাস থেকে কিছু সহায়তা পেতে পারেন । ওয়ান-লাইনার হিসাবে ভূমিকা চেক করা:

if (AuthorityUtils.authorityListToSet(SecurityContextHolder.getContext().getAuthentication().getAuthorities()).contains("ROLE_MANAGER")) {
    /* ... */
}

ক্যাভ্যাট: এটি ভূমিকা শ্রেণিবিন্যাস পরীক্ষা করে না, যদি এর উপস্থিত থাকে।


এটিই সহজ সমাধান কারণ যেটি আমাকে বেশ কয়েকবার তালিকাগুলি পরীক্ষা করা প্রয়োজন এবং কিছু ম্যাজিক সাধারণ রুটিন দিয়ে একবার এনে নেওয়া দুর্দান্ত!
লিও

6

আপনার পরিষেবা স্তরে যখন আপনি HTTP অনুরোধের রেফারেন্স থেকে ওয়েব স্তরের সাথে একটি মিলিত পরিচয় দিতে চান না তখন জোসেকের উত্তরটি ব্যবহার করা যাবে না। আপনি যদি পরিষেবা স্তরে থাকাকালীন ভূমিকাগুলি সমাধান করার দিকে নজর রাখেন তবে গোপীর উত্তরটি যাওয়ার উপায়।

যাইহোক, এটি কিছুটা দীর্ঘ বাতাসে। কর্তৃপক্ষগুলি সরাসরি প্রমাণীকরণ থেকে অ্যাক্সেস করা যায়। অতএব, আপনি যদি ধরে নিতে পারেন যে আপনার কোনও ব্যবহারকারী লগ ইন করেছেন, নিম্নলিখিতটি এটি করে:

/**
 * @return true if the user has one of the specified roles.
 */
protected boolean hasRole(String[] roles) {
    boolean result = false;
    for (GrantedAuthority authority : SecurityContextHolder.getContext().getAuthentication().getAuthorities()) {
        String userRole = authority.getAuthority();
        for (String role : roles) {
            if (role.equals(userRole)) {
                result = true;
                break;
            }
        }

        if (result) {
            break;
        }
    }

    return result;
}

6

সর্বাধিক উত্তরগুলি কিছু পয়েন্ট অনুপস্থিত:

  1. ভূমিকা এবং কর্তৃত্ব বসন্তে একই জিনিস নয়। আরও বিশদ জন্য এখানে দেখুন।

  2. ভূমিকার নামগুলি rolePrefix+ এর সমান authority

  3. ডিফল্ট ভূমিকা উপসর্গ ROLE_, এটি কনফিগারযোগ্য। এখানে দেখুন ।

অতএব, একটি যথাযথ ভূমিকা চেকটি কনফিগার করা থাকলে ভূমিকা উপসর্গটিকে সম্মান করা দরকার।

দুর্ভাগ্যক্রমে, স্প্রিংয়ের ভূমিকা উপসর্গ কাস্টমাইজেশনটি কিছুটা হ্যাকি, অনেক স্থানে ডিফল্ট উপসর্গটি ROLE_হার্ডকোডযুক্ত, তবে GrantedAuthorityDefaultsএটির পাশাপাশি, বসন্তের প্রেক্ষাপটে একটি শিমের প্রকারের পরীক্ষা করা হয় এবং এটি উপস্থিত থাকলে কাস্টম রোলটি উপসর্গ করে তোলে সম্মানিত হয়।

এই সমস্ত তথ্য একত্রিত করা, আরও ভাল ভূমিকা চেকার বাস্তবায়ন এরকম কিছু হবে:

@Component
public class RoleChecker {

    @Autowired(required = false)
    private GrantedAuthorityDefaults grantedAuthorityDefaults;

    public boolean hasRole(String role) {
        String rolePrefix = grantedAuthorityDefaults != null ? grantedAuthorityDefaults.getRolePrefix() : "ROLE_";
        return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
                .map(Authentication::getAuthorities)
                .map(Collection::stream)
                .orElse(Stream.empty())
                .map(GrantedAuthority::getAuthority)
                .map(authority -> rolePrefix + authority)
                .anyMatch(role::equals);
    }
}

3

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


সুতরাং আপনার সমাধানটি হ'ল ডিফল্টমেথডসিকিউরিটিএক্সগ্রেশনহ্যান্ডলারকে বিন হিসাবে ব্যবহার করা এবং এক্সপ্রেশন পার্সার পাওয়া এবং এটি EL তে পরীক্ষা করা?
পাইটর গুইয়াজদা

এটি সম্ভবত কাজ করবে না, কারণ হ্যান্ডলারটি পদ্ধতি পদ্ধতিতে চালিত হয় (যা আপনার প্রসঙ্গে নেই)। আপনাকে সম্ভবত আপনার নিজস্ব শিম তৈরি করতে হবে যা একই রকম কিছু করে তবে কোনও পদ্ধতিগত প্রসঙ্গটি ব্যবহার না করে
সান প্যাট্রিক ফ্লয়েড

2

আরও বেশি দেরি না হলে কখনই না, আমাকে আমার 2 সেন্ট মূল্য রাখুন।

জেএসএফ বিশ্বে, আমার পরিচালিত শিমের মধ্যে, আমি নিম্নলিখিতগুলি করেছি:


HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
SecurityContextHolderAwareRequestWrapper sc = new SecurityContextHolderAwareRequestWrapper(req, "");

উপরে উল্লিখিত হিসাবে, আমার বোধগম্যতা হ'ল এটি অনুসরণ করা দীর্ঘ বাঁকানো পথে করা যেতে পারে:


Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserDetails userDetails = null;
if (principal instanceof UserDetails) {
    userDetails = (UserDetails) principal;
    Collection  authorities = userDetails.getAuthorities();
}

2

এটি অন্য প্রান্ত থেকে প্রশ্নে আসার মতো, তবে আমি ভেবেছিলাম যে এটি খুঁজে পেতে আমি সত্যিই ইন্টারনেটে খনন করতে হয়েছিল as

কীভাবে ভূমিকাগুলি যাচাই করা যায় তা সম্পর্কে প্রচুর স্টাফ রয়েছে তবে আপনি যখন হ'স রোল বলবেন তখন আসলে আপনি যা যাচাই করছেন তা খুব বেশি বলছেন না ("ব্লাহ")

হাসরোল বর্তমানে অনুমোদনপ্রাপ্ত অধ্যক্ষের জন্য অনুমোদিত কর্তৃপক্ষগুলি পরীক্ষা করে

সুতরাং যখন আপনি রোল ("ব্লাহ") দেখতে পাচ্ছেন তার সত্যিকার অর্থেই হ'লঅ্যাক্সার্টিটি ("ব্লাহ")

আমি দেখেছি এমন ক্ষেত্রে, আপনি এমন একটি শ্রেণীর সাথে এটি করেন যা ব্যবহারকারীর বিবরণগুলি কার্যকর করে যা getAuthorities নামে একটি পদ্ধতি নির্ধারণ করে। এতে আপনি মূলত কিছু যুক্ত করবেনnew SimpleGrantedAuthority("some name") কিছু যুক্তির উপর ভিত্তি করে একটি তালিকায় কিছু যুক্ত করবেন। এই তালিকার নামগুলি হ'রোল স্টেটমেন্ট দ্বারা পরীক্ষা করা জিনিস।

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


2
স্প্রিং সিকিউরিটি ৪.০ হিসাবে hasRole("bla")এটি এখন সমান hasAuthority("ROLE_bla")
ল্যানক্সিক্স

2

@ গৌকি উত্তরটি সবচেয়ে ভাল!

কীভাবে বসন্ত এটি সত্যিই করে তার একটি টিপ।

নামের একটি শ্রেণি রয়েছে SecurityContextHolderAwareRequestWrapperযা প্রয়োগ করেServletRequestWrapper ক্লাস ।

SecurityContextHolderAwareRequestWrapperওভাররাইড isUserInRoleএবং সার্চ ব্যবহারকারীAuthentication যদি ব্যবহারকারী একটি ভূমিকা আছে কি না (যা স্প্রিং দ্বারা পরিচালিত হয়) খুঁজে।

SecurityContextHolderAwareRequestWrapper কোডটি হ'ল:

    @Override
    public boolean isUserInRole(String role) {
        return isGranted(role);
    }

 private boolean isGranted(String role) {
        Authentication auth = getAuthentication();

        if( rolePrefix != null ) {
            role = rolePrefix + role;
        }

        if ((auth == null) || (auth.getPrincipal() == null)) {
            return false;
        }

        Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();

        if (authorities == null) {
            return false;
        }

        //This is the loop which do actual search
        for (GrantedAuthority grantedAuthority : authorities) {
            if (role.equals(grantedAuthority.getAuthority())) {
                return true;
            }
        }

        return false;
    }

2

নীচে এই দুটি টীকা সমান, "hasRole" স্বয়ংক্রিয়ভাবে "ROLE_" উপসর্গ যুক্ত করবে। আপনার সঠিক টিকা আছে কিনা তা নিশ্চিত করুন। এই ভূমিকাটি ইউজারডেটেলস সার্ভিস # লোডউজারবিউসারনেমে সেট করা আছে।

@PreAuthorize("hasAuthority('ROLE_user')")
@PreAuthorize("hasRole('user')")

তারপরে, আপনি জাভা কোডে ভূমিকা পেতে পারেন।

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if(authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_user"))){
    System.out.println("user role2");
}

1

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

এর সমাধান:

@Component
public class SpringRoleEvaluator {

@Resource(name="roleHierarchy")
private RoleHierarchy roleHierarchy;

public boolean hasRole(String role) {
    UserDetails dt = AuthenticationUtils.getSessionUserDetails();

    for (GrantedAuthority auth: roleHierarchy.getReachableGrantedAuthorities(dt.getAuthorities())) {
        if (auth.toString().equals("ROLE_"+role)) {
            return true;
        }
    }
    return false;
}

RoleHierarchy বসন্ত-সুরক্ষা.এক্সএমএলে মটরশুটি হিসাবে সংজ্ঞায়িত করা হয়।


1
অথবা আপনি আপনার ভূমিকা যথাযথভাবে পপুলেশন
আর্কটিকা

1

আপনার ব্যবহারকারীর মডেলটিতে নীচের মতো একটি 'হ্যাশ রোল' পদ্ধতি যুক্ত করুন

public boolean hasRole(String auth) {
    for (Role role : roles) {
        if (role.getName().equals(auth)) { return true; }
    }
    return false;
}

আমি সাধারণত এটি ব্যবহার করে যাচাই করা ব্যবহারকারীর নীচের মতো ভূমিকা প্রশাসক রয়েছে কিনা তা যাচাই করতে এটি ব্যবহার করি

Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); // This gets the authentication
User authUser = (User) authentication.getPrincipal(); // This gets the logged in user
authUser.hasRole("ROLE_ADMIN") // This returns true or false

1

নিম্নলিখিত পদ্ধতি ব্যবহার করে ব্যবহারকারীর ভূমিকাগুলি পরীক্ষা করা যেতে পারে:

  1. সিকিউরিটি কনটেক্সটহোল্ডারে কল স্ট্যাটিক পদ্ধতি ব্যবহার করে:

    Authentication auth = SecurityContextHolder.getContext().getAuthentication(); if (auth != null && auth.getAuthorities().stream().anyMatch(role -> role.getAuthority().equals("ROLE_NAME"))) { //do something}

  2. HttpServletRequest ব্যবহার করে

@GetMapping("/users")
public String getUsers(HttpServletRequest request) {
    if (request.isUserInRole("ROLE_NAME")) {
      
    }


0

জাভা 8 এর সহায়তায় আমার অ্যাপ্রোচ, পাসিং কোমা বিচ্ছিন্ন ভূমিকা আপনাকে সত্য বা মিথ্যা দেবে

    public static Boolean hasAnyPermission(String permissions){
    Boolean result = false;
    if(permissions != null && !permissions.isEmpty()){
        String[] rolesArray = permissions.split(",");
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        for (String role : rolesArray) {
            boolean hasUserRole = authentication.getAuthorities().stream().anyMatch(r -> r.getAuthority().equals(role));
            if (hasUserRole) {
                result = true;
                break;
            }
        }
    }
    return result;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.