سؤال

كيفية التحقق من سلطة المستخدم أو إذن في رمز Java؟ على سبيل المثال - أريد أن أعرض أو إخفاء زر المستخدم اعتمادًا على الدور. هناك تعليقات توضيحية مثل:

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

كيف تجعلها في كود جافا؟ شيء مثل :

if(somethingHere.hasRole("ROLE_MANAGER")) {
   layout.addComponent(new Button("Edit users"));
}
هل كانت مفيدة؟

المحلول

Spring Security 3.0 لديه API هذا

SecurityContextHolderAwareRequestWrapper.isUserInRole(String role)

سيتعين عليك حقن الغلاف ، قبل استخدامه.

SecurityContextholderawareRequestWrapper

نصائح أخرى

يمكنك استخدام طريقة IsuserInrole لكائن httpservletrequest.

شيء مثل:

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


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

بدلاً من استخدام حلقة للعثور على السلطة من userDetails التي يمكنك القيام بها:

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

يمكنك استرداد سياق الأمان ثم استخدام ذلك:

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

يمكنك تنفيذ طريقة Hasrole () على النحو التالي - (يتم اختبار هذا على Spring Security 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;
  }

أنا أستخدم هذا:

@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);
}

يمكنك الحصول على بعض المساعدة من سلطة صف دراسي. التحقق من الدور باعتباره خط واحد:

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

التحذير: هذا لا يتحقق من التسلسل الهرمي للدور ، إذا كان هذا موجودًا.

لا يمكن استخدام الإجابة من جوزيك عند طبقة الخدمة الخاصة بك ، حيث لا ترغب في تقديم اقتران مع طبقة الويب من المرجع إلى طلب HTTP. إذا كنت تبحث في حل الأدوار أثناء وجودها في طبقة الخدمة ، فإن إجابة Gopi هي الطريق للذهاب.

ومع ذلك ، فقد انتهى لفترة طويلة. يمكن الوصول إلى السلطات مباشرة من المصادقة. وبالتالي ، إذا كنت تستطيع افتراض أن لديك مستخدمًا قام بتسجيل الدخول ، فإن ما يلي يفعل ذلك:

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

معظم الإجابات تفتقد بعض النقاط:

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

الغريب بما فيه الكفاية ، لا أعتقد أن هناك حلًا قياسيًا لهذه المشكلة ، لأن التحكم في الوصول إلى أمن الربيع تعبير على أساس, ، وليس على أساس جافا. يمكنك التحقق من الرمز المصدر لDefaultMethodSecurityExpressionHandler لمعرفة ما إذا كان يمكنك إعادة استخدام شيء يفعلونه هناك

من الأفضل متأخراً بعد ذلك ، دعني أضع قيمتي في سنتين.

في عالم JSF ، داخل الفول المدار ، فعلت ما يلي:


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();
}

الجواب gouki هو الأفضل!

مجرد نصيحة لكيفية قيام الربيع بذلك حقًا.

هناك فصل اسمه 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;
    }

هذان التعليقين أدناه متساوين ، "Hassrole" سوف يضيف بادئة "الدور_". تأكد من أن لديك التعليق التوضيحي الصحيح. تم تعيين هذا الدور في userDetailsService#LoadUserByuserName.

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

بعد ذلك ، يمكنك الحصول على الدور في كود Java.

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

هذا نوع من السؤال من الطرف الآخر ، لكنني اعتقدت أنني سأرميه لأنني اضطررت حقًا إلى البحث على الإنترنت لمعرفة ذلك.

هناك الكثير من الأشياء حول كيفية التحقق من الأدوار ولكن لا تقل كثيرًا ما تتفقده فعليًا عند قول هاسول ("بلاه")

يتحقق Hasrole من السلطات الممنوحة للمدير المصادق عليه حاليًا

حقا عندما ترى هاسول ("بلاه") يعني حقًا hasauthority ("بلاه").

في الحالة التي رأيتها ، يمكنك القيام بذلك مع فئة تنفذ userDetails التي تحدد طريقة تسمى getAuthorities. في هذا سوف تضيف بعضًا بشكل أساسي new SimpleGrantedAuthority("some name") إلى قائمة بناء على بعض المنطق. الأسماء الواردة في هذه القائمة هي الأشياء التي تم فحصها بواسطة عبارات Hassrole.

أعتقد في هذا السياق أن كائن userDetails هو المدير المصادق عليه حاليًا. هناك بعض السحر الذي يحدث في مزودي المصادقة وحوله ، وبشكل أكثر تحديداً مديرة المصادقة التي تجعل هذا يحدث.

في مشروعنا ، نستخدم التسلسل الهرمي للدور ، في حين أن معظم الإجابات المذكورة أعلاه تهدف فقط إلى التحقق من دور معين ، أي سيتحقق فقط من الدور المقدم ، ولكن ليس لهذا الدور وأعلى التسلسل الهرمي.

حل لهذا:

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

يتم تعريف التسلسل الهرمي على أنه حبة في الربيع security.xml.

نهجي بمساعدة Java8 ، سوف يمنحك الأدوار المنفصلة عن الغيبوبة الحقيقية أو خاطئة

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

على نموذج المستخدم الخاص بك ، فقط أضف طريقة "Hassrole" كما أدناه

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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top