/**
   * Extracts user groups from {@link SecurityRealm}.
   *
   * @param userId
   * @return List of effective groups. Null if there's no info
   */
  private static @CheckForNull List<String> getAuthoritiesFromRealm(@Nonnull String userId) {
    final Jenkins instance = Jenkins.getInstance();
    if (instance == null) {
      return null; // Jenkins has not been started yet
    }

    @CheckForNull UserDetails userDetails = null;
    try {
      final SecurityRealm sr = instance.getSecurityRealm();
      userDetails = sr.loadUserByUsername(userId);
    } catch (DataAccessException ex) {
      // fallback to null handler
    } catch (UsernameNotFoundException ex) {
      // fallback to null handler
    }

    if (userDetails == null) {
      return null;
    }

    GrantedAuthority[] authorities = userDetails.getAuthorities();
    List<String> authorityList = new ArrayList<String>(authorities.length);
    for (GrantedAuthority auth : authorities) {
      authorityList.add(auth.getAuthority());
    }
    return authorityList;
  }
 public void modifyUserInCache(UserDetails u) {
   log.warn("修改用户[" + u.getUsername() + "]的缓存");
   if (this.getUserCache().getUserFromCache(u.getUsername()) != null) {
     this.getUserCache().removeUserFromCache(u.getUsername());
   }
   // 重新从数据库中取得修改后的用户信息,包括相关的权限信息
   u = userDao.loadUserByUsername(((User) u).getLoginId());
   this.putUserInCache(u);
 }
  public void testLoadUserByConfiguredImId() {
    CoreContext coreContext = createMock(CoreContext.class);
    UserDetails details = null;
    try {
      details = getUserDetailsTestService(coreContext, false).loadUserByUsername(USER_IM_ID);
      fail();
    } catch (UsernameNotFoundException e) {
      assertTrue(e.getMessage().contains(USER_IM_ID));
    }

    verify(coreContext);

    CoreContext coreContext1 = createMock(CoreContext.class);
    details = getUserDetailsTestService(coreContext1, true).loadUserByUsername(USER_IM_ID);
    assertEquals(USER_IM_ID, details.getUsername());

    verify(coreContext);
  }
  public void testFill() throws Exception {
    Locale.setDefault(Locale.ENGLISH);

    // make sure the recorder is where we think it is, it contains the palette selection
    tester.assertComponent("userForm:roles:roles:recorder", Recorder.class);

    // try to add a new user
    FormTester form = tester.newFormTester("userForm");
    form.setValue("username", "user");
    form.setValue("password", "pwd");
    form.setValue("confirmPassword", "pwd");
    // note: use a known role, there is no way to add a new role using wickettester support
    form.setValue("roles:roles:recorder", dao.getRoles().get(0));
    form.submit("save");

    tester.assertErrorMessages(new String[0]);
    tester.assertRenderedPage(UserPage.class);

    dao.reload();
    UserDetails user = dao.loadUserByUsername("user");
    assertEquals("pwd", user.getPassword());
    assertEquals(1, user.getAuthorities().length);
  }
  public void testLoadUserByUsername() {
    User u =
        new User() {
          @Override
          public boolean hasPermission(PermissionName permission) {
            return true;
          }
        };
    u.setUserName(USER_NAME);
    u.setUniqueId();

    CoreContext coreContext = createMock(CoreContext.class);
    AcdContext acdContext = createMock(AcdContext.class);
    StandardUserDetailsService uds = new StandardUserDetailsService();
    uds.setCoreContext(coreContext);
    uds.setAcdContext(acdContext);

    coreContext.loadUserByUserNameOrAlias(USER_NAME);
    expectLastCall().andReturn(u);

    acdContext.getUsersWithAgents();
    expectLastCall().andReturn(Collections.emptyList());
    replay(coreContext, acdContext);

    // load the user details
    UserDetails details = uds.loadUserByUsername(USER_NAME);
    assertEquals(USER_NAME, details.getUsername());
    GrantedAuthority[] authorities = details.getAuthorities();

    assertTrue(contains(authorities, UserRole.Admin.toAuth()));
    assertTrue(contains(authorities, UserRole.User.toAuth()));
    assertFalse(contains(authorities, UserRole.AcdAgent.toAuth()));
    assertFalse(contains(authorities, UserRole.AcdSupervisor.toAuth()));
    assertTrue(contains(authorities, UserRole.AttendantAdmin.toAuth()));

    verify(coreContext, acdContext);
  }
예제 #6
0
  public UserDetails loadUserByUsername(String username)
      throws UsernameNotFoundException, DataAccessException {
    List users = usersByUsernameMapping.execute(username);

    if (users.size() == 0) {
      throw new UsernameNotFoundException("User not found");
    }

    UserDetails user = (UserDetails) users.get(0); // contains no GrantedAuthority[]

    List dbAuths = authoritiesByUsernameMapping.execute(user.getUsername());

    addCustomAuthorities(user.getUsername(), dbAuths);

    if (dbAuths.size() == 0) {
      throw new UsernameNotFoundException("User has no GrantedAuthority");
    }

    // 源代码的写法
    // GrantedAuthority[] arrayAuths = (GrantedAuthority[]) dbAuths.toArray(new
    // GrantedAuthority[dbAuths.size()]);

    // 朱华茜的修改 因为角色是用逗号分隔的 所以不能直接使用数据库中拿到的字符串 这样只会得到一个不存在的GrantedAuthorityImpl 而我们需要多个以实现角色的叠加
    GrantedAuthorityImpl tempGrantedAuthorityImpl = (GrantedAuthorityImpl) dbAuths.get(0);
    String[] roles = tempGrantedAuthorityImpl.getAuthority().split(",");
    GrantedAuthority[] arrayAuths = new GrantedAuthority[roles.length];
    for (int i = 0; i < roles.length; i++) {
      arrayAuths[i] = new GrantedAuthorityImpl(roles[i]);
    }

    String returnUsername = user.getUsername();

    if (!usernameBasedPrimaryKey) {
      returnUsername = username;
    }

    return new User(
        returnUsername, user.getPassword(), user.isEnabled(), true, true, true, arrayAuths);
  }
 public void putUserInCache(UserDetails u) {
   log.warn("将用户[" + u.getUsername() + "]加入到用户缓存中");
   this.getUserCache().putUserInCache(u);
 }
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    if (!(request instanceof HttpServletRequest)) {
      throw new ServletException("Can only process HttpServletRequest");
    }

    if (!(response instanceof HttpServletResponse)) {
      throw new ServletException("Can only process HttpServletResponse");
    }

    HttpServletRequest httpRequest = (HttpServletRequest) request;

    String header = httpRequest.getHeader("Authorization");

    if (logger.isDebugEnabled()) {
      logger.debug("Authorization header received from user agent: " + header);
    }

    if ((header != null) && header.startsWith("Digest ")) {
      String section212response = header.substring(7);

      String[] headerEntries = StringSplitUtils.splitIgnoringQuotes(section212response, ',');
      Map headerMap = StringSplitUtils.splitEachArrayElementAndCreateMap(headerEntries, "=", "\"");

      String username = (String) headerMap.get("username");
      String realm = (String) headerMap.get("realm");
      String nonce = (String) headerMap.get("nonce");
      String uri = (String) headerMap.get("uri");
      String responseDigest = (String) headerMap.get("response");
      String qop = (String) headerMap.get("qop"); // RFC 2617 extension
      String nc = (String) headerMap.get("nc"); // RFC 2617 extension
      String cnonce = (String) headerMap.get("cnonce"); // RFC 2617 extension

      // Check all required parameters were supplied (ie RFC 2069)
      if ((username == null)
          || (realm == null)
          || (nonce == null)
          || (uri == null)
          || (response == null)) {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "extracted username: '******'; realm: '"
                  + username
                  + "'; nonce: '"
                  + username
                  + "'; uri: '"
                  + username
                  + "'; response: '"
                  + username
                  + "'");
        }

        fail(
            request,
            response,
            new BadCredentialsException(
                messages.getMessage(
                    "DigestProcessingFilter.missingMandatory",
                    new Object[] {section212response},
                    "Missing mandatory digest value; received header {0}")));

        return;
      }

      // Check all required parameters for an "auth" qop were supplied (ie RFC 2617)
      if ("auth".equals(qop)) {
        if ((nc == null) || (cnonce == null)) {
          if (logger.isDebugEnabled()) {
            logger.debug("extracted nc: '" + nc + "'; cnonce: '" + cnonce + "'");
          }

          fail(
              request,
              response,
              new BadCredentialsException(
                  messages.getMessage(
                      "DigestProcessingFilter.missingAuth",
                      new Object[] {section212response},
                      "Missing mandatory digest value; received header {0}")));

          return;
        }
      }

      // Check realm name equals what we expected
      if (!this.getAuthenticationEntryPoint().getRealmName().equals(realm)) {
        fail(
            request,
            response,
            new BadCredentialsException(
                messages.getMessage(
                    "DigestProcessingFilter.incorrectRealm",
                    new Object[] {realm, this.getAuthenticationEntryPoint().getRealmName()},
                    "Response realm name '{0}' does not match system realm name of '{1}'")));

        return;
      }

      // Check nonce was a Base64 encoded (as sent by DigestProcessingFilterEntryPoint)
      if (!Base64.isArrayByteBase64(nonce.getBytes())) {
        fail(
            request,
            response,
            new BadCredentialsException(
                messages.getMessage(
                    "DigestProcessingFilter.nonceEncoding",
                    new Object[] {nonce},
                    "Nonce is not encoded in Base64; received nonce {0}")));

        return;
      }

      // Decode nonce from Base64
      // format of nonce is:
      //   base64(expirationTime + ":" + md5Hex(expirationTime + ":" + key))
      String nonceAsPlainText = new String(Base64.decodeBase64(nonce.getBytes()));
      String[] nonceTokens = StringUtils.delimitedListToStringArray(nonceAsPlainText, ":");

      if (nonceTokens.length != 2) {
        fail(
            request,
            response,
            new BadCredentialsException(
                messages.getMessage(
                    "DigestProcessingFilter.nonceNotTwoTokens",
                    new Object[] {nonceAsPlainText},
                    "Nonce should have yielded two tokens but was {0}")));

        return;
      }

      // Extract expiry time from nonce
      long nonceExpiryTime;

      try {
        nonceExpiryTime = new Long(nonceTokens[0]).longValue();
      } catch (NumberFormatException nfe) {
        fail(
            request,
            response,
            new BadCredentialsException(
                messages.getMessage(
                    "DigestProcessingFilter.nonceNotNumeric",
                    new Object[] {nonceAsPlainText},
                    "Nonce token should have yielded a numeric first token, but was {0}")));

        return;
      }

      // Check signature of nonce matches this expiry time
      String expectedNonceSignature =
          DigestUtils.md5Hex(nonceExpiryTime + ":" + this.getAuthenticationEntryPoint().getKey());

      if (!expectedNonceSignature.equals(nonceTokens[1])) {
        fail(
            request,
            response,
            new BadCredentialsException(
                messages.getMessage(
                    "DigestProcessingFilter.nonceCompromised",
                    new Object[] {nonceAsPlainText},
                    "Nonce token compromised {0}")));

        return;
      }

      // Lookup password for presented username
      // NB: DAO-provided password MUST be clear text - not encoded/salted
      // (unless this instance's passwordAlreadyEncoded property is 'false')
      boolean loadedFromDao = false;
      UserDetails user = userCache.getUserFromCache(username);

      if (user == null) {
        loadedFromDao = true;

        try {
          user = userDetailsService.loadUserByUsername(username);
        } catch (UsernameNotFoundException notFound) {
          fail(
              request,
              response,
              new BadCredentialsException(
                  messages.getMessage(
                      "DigestProcessingFilter.usernameNotFound",
                      new Object[] {username},
                      "Username {0} not found")));

          return;
        }

        if (user == null) {
          throw new AuthenticationServiceException(
              "AuthenticationDao returned null, which is an interface contract violation");
        }

        userCache.putUserInCache(user);
      }

      // Compute the expected response-digest (will be in hex form)
      String serverDigestMd5;

      // Don't catch IllegalArgumentException (already checked validity)
      serverDigestMd5 =
          generateDigest(
              passwordAlreadyEncoded,
              username,
              realm,
              user.getPassword(),
              ((HttpServletRequest) request).getMethod(),
              uri,
              qop,
              nonce,
              nc,
              cnonce);

      // If digest is incorrect, try refreshing from backend and recomputing
      if (!serverDigestMd5.equals(responseDigest) && !loadedFromDao) {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Digest comparison failure; trying to refresh user from DAO in case password had changed");
        }

        try {
          user = userDetailsService.loadUserByUsername(username);
        } catch (UsernameNotFoundException notFound) {
          // Would very rarely happen, as user existed earlier
          fail(
              request,
              response,
              new BadCredentialsException(
                  messages.getMessage(
                      "DigestProcessingFilter.usernameNotFound",
                      new Object[] {username},
                      "Username {0} not found")));
        }

        userCache.putUserInCache(user);

        // Don't catch IllegalArgumentException (already checked validity)
        serverDigestMd5 =
            generateDigest(
                passwordAlreadyEncoded,
                username,
                realm,
                user.getPassword(),
                ((HttpServletRequest) request).getMethod(),
                uri,
                qop,
                nonce,
                nc,
                cnonce);
      }

      // If digest is still incorrect, definitely reject authentication attempt
      if (!serverDigestMd5.equals(responseDigest)) {
        if (logger.isDebugEnabled()) {
          logger.debug(
              "Expected response: '"
                  + serverDigestMd5
                  + "' but received: '"
                  + responseDigest
                  + "'; is AuthenticationDao returning clear text passwords?");
        }

        fail(
            request,
            response,
            new BadCredentialsException(
                messages.getMessage(
                    "DigestProcessingFilter.incorrectResponse", "Incorrect response")));

        return;
      }

      // To get this far, the digest must have been valid
      // Check the nonce has not expired
      // We do this last so we can direct the user agent its nonce is stale
      // but the request was otherwise appearing to be valid
      if (nonceExpiryTime < System.currentTimeMillis()) {
        fail(
            request,
            response,
            new NonceExpiredException(
                messages.getMessage(
                    "DigestProcessingFilter.nonceExpired", "Nonce has expired/timed out")));

        return;
      }

      if (logger.isDebugEnabled()) {
        logger.debug(
            "Authentication success for user: '******' with response: '"
                + responseDigest
                + "'");
      }

      // START SIPXECS CUSTOM CODE: XX-8253
      // commented original code
      // UsernamePasswordAuthenticationToken authRequest = new
      // UsernamePasswordAuthenticationToken(user,
      //        user.getPassword());

      // creates digest token to be handled by
      // org.sipfoundry.sipxconfig.security.DaoAuthenticationProvider
      UsernamePasswordAuthenticationToken authRequest =
          new DigestUsernamePasswordAuthenticationToken(user, user.getPassword());
      // END SIPXECS CUSTOM CODE: XX-8253
      authRequest.setDetails(
          authenticationDetailsSource.buildDetails((HttpServletRequest) request));

      SecurityContextHolder.getContext().setAuthentication(authRequest);
    }

    chain.doFilter(request, response);
  }