@Override protected AuthenticationInfo queryForAuthenticationInfo( AuthenticationToken token, LdapContextFactory contextFactory) throws NamingException { logger.debug( "queryForAuthenticationInfo, principal: {}, credentials: *****", token.getPrincipal()); logger.debug("contextFactory : {}", contextFactory); try { if (token == null || token.getPrincipal() == null) { logger.info("No authentication token provided, will not try to authenticate.."); return null; } LdapContext sysCtx = contextFactory.getSystemLdapContext(); String objClsFilter = createObjectClassFilter(objectClasses); String userIdFilter = createAttributeFilter(userIdAttribute, token.getPrincipal().toString()); String filter = mergeFiltersAND(objClsFilter, userIdFilter); NamingEnumeration<?> namingEnumeration = sysCtx.search(config.getUserLdapBaseDn(), filter, getSimpleSearchControls()); while (namingEnumeration.hasMore()) { SearchResult result = (SearchResult) namingEnumeration.next(); String dn = result.getNameInNamespace(); try { contextFactory.getLdapContext(dn, token.getCredentials()); return new SimpleAuthenticationInfo(dn, token.getCredentials(), "StaticRealm"); } catch (Exception e) { logger.error(e.getMessage(), e); } } } catch (Exception e) { logger.error(e.getMessage(), e); } return null; }
/** * Returns the {@link AuthenticationInfo} resulting from a Subject's successful LDAP * authentication attempt. * * <p>This implementation ignores the {@code ldapPrincipal}, {@code ldapCredentials}, and the * opened {@code ldapContext} arguments and merely returns an {@code AuthenticationInfo} instance * mirroring the submitted token's principal and credentials. This is acceptable because this * method is only ever invoked after a successful authentication attempt, which means the provided * principal and credentials were correct, and can be used directly to populate the (now verified) * {@code AuthenticationInfo}. * * <p>Subclasses however are free to override this method for more advanced construction logic. * * @param token the submitted {@code AuthenticationToken} that resulted in a successful * authentication * @param ldapPrincipal the LDAP principal used when creating the LDAP connection. Unlike the * token's {@link AuthenticationToken#getPrincipal() principal}, this value is usually a * constructed User DN and not a simple username or uid. The exact value is depending on the * configured <a * href="http://download-llnw.oracle.com/javase/tutorial/jndi/ldap/auth_mechs.html">LDAP * authentication mechanism</a> in use. * @param ldapCredentials the LDAP credentials used when creating the LDAP connection. * @param ldapContext the LdapContext created that resulted in a successful authentication. It can * be used further by subclasses for more complex operations. It does not need to be closed - * it will be closed automatically after this method returns. * @return the {@link AuthenticationInfo} resulting from a Subject's successful LDAP * authentication attempt. * @throws NamingException if there was any problem using the {@code LdapContext} */ @SuppressWarnings({"UnusedDeclaration"}) protected AuthenticationInfo createAuthenticationInfo( AuthenticationToken token, Object ldapPrincipal, Object ldapCredentials, LdapContext ldapContext) throws NamingException { return new SimpleAuthenticationInfo(token.getPrincipal(), token.getCredentials(), getName()); }
// 登录信息和用户验证信息验证 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = (String) token.getPrincipal(); // 得到用户名 String password = new String((char[]) token.getCredentials()); // 得到密码 if (null != username && null != password) { return new SimpleAuthenticationInfo(username, password, getName()); } else { return null; } }
@Override public AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = (String) token.getPrincipal(); // 得到用户名 String password = new String((char[]) token.getCredentials()); // 得到用户密码 if (!"zhang".equals(username)) { throw new UnknownAccountException(); // 如果用户名不对 } if (!"123456".equals(password)) { throw new IncorrectCredentialsException(); } // 如果身份认证成功,返回AuthenticationInfo实现 return new SimpleAuthenticationInfo(username, password, getName()); }
@Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = (String) token.getPrincipal(); // 得到用户名 String password = new String((char[]) token.getCredentials()); // 得到密码 if (!"zhang".equals(username)) { throw new UnknownAccountException(); // 如果用户名错误 } if (!"123".equals(password)) { throw new IncorrectCredentialsException(); // 如果密码错误 } // 如果身份认证验证成功,返回一个AuthenticationInfo实现; return new SimpleAuthenticationInfo(username, password, getName()); }
// 验证用户 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String loginName = (String) token.getPrincipal(); // 得到用户名 String password = new String((char[]) token.getCredentials()); // 得到密码 User user = new User(); user.setLoginName(loginName); user.setPassword(password); User loginUser = adminUserDao.login(user.getLoginName(), user.getPassword()); if (loginUser == null || loginUser.getId() <= 0) { throw new IncorrectCredentialsException("用户名或密码不正确!"); } // 如果身份认证验证成功,返回一个 AuthenticationInfo 实现; return new SimpleAuthenticationInfo(loginName, password, getName()); }
@Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { User user = (User) token.getPrincipal(); if (user == null) { throw new UnknownAccountException( ConstantsUtility.ERROR_MESSAGES.getString("userDoesNotExist")); } else if (!user.isActive()) { throw new LockedAccountException(ConstantsUtility.ERROR_MESSAGES.getString("userInactive")); } else if (user.isLocked()) { throw new LockedAccountException(ConstantsUtility.ERROR_MESSAGES.getString("userLocked")); } SimplePrincipalCollection principles = new SimplePrincipalCollection(); principles.add(user, ConstantsUtility.OAUTH_REALM_NAME); return new SimpleAuthenticationInfo(principles, token.getCredentials()); }
/** * This implementation opens an LDAP connection using the token's {@link * #getLdapPrincipal(org.apache.shiro.authc.AuthenticationToken) discovered principal} and * provided {@link AuthenticationToken#getCredentials() credentials}. If the connection opens * successfully, the authentication attempt is immediately considered successful and a new {@link * AuthenticationInfo} instance is {@link * #createAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken, Object, Object, * javax.naming.ldap.LdapContext) created} and returned. If the connection cannot be opened, * either because LDAP authentication failed or some other JNDI problem, an {@link * NamingException} will be thrown. * * @param token the submitted authentication token that triggered the authentication attempt. * @param ldapContextFactory factory used to retrieve LDAP connections. * @return an {@link AuthenticationInfo} instance representing the authenticated user's * information. * @throws NamingException if any LDAP errors occur. */ protected AuthenticationInfo queryForAuthenticationInfo( AuthenticationToken token, LdapContextFactory ldapContextFactory) throws NamingException { Object principal = token.getPrincipal(); Object credentials = token.getCredentials(); log.debug("Authenticating user '{}' through LDAP", principal); principal = getLdapPrincipal(token); LdapContext ctx = null; try { ctx = ldapContextFactory.getLdapContext(principal, credentials); // context was opened successfully, which means their credentials were valid. Return the // AuthenticationInfo: return createAuthenticationInfo(token, principal, credentials, ctx); } finally { LdapUtils.closeContext(ctx); } }
@Override protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) { String authorizationHeader = getAuthzHeader(request); if (authorizationHeader == null || authorizationHeader.length() == 0) { // Create an empty authentication token since there is no // Authorization header. return createToken("", "", request, response); } if (log.isDebugEnabled()) { log.debug("Attempting to execute login with headers [" + authorizationHeader + "]"); } String[] prinCred = getPrincipalsAndCredentials(authorizationHeader, request); if (prinCred == null || prinCred.length < 2) { // Create an authentication token with an empty password, // since one hasn't been provided in the request. String username = prinCred == null || prinCred.length == 0 ? "" : prinCred[0]; return createToken(username, "", request, response); } String username = prinCred[0]; String password = prinCred[1]; String sf = SF.replace("{0}", username); try { AuthenticationToken at = new UsernamePasswordToken(MessagingServletConfig.ldapUser, MessagingServletConfig.ldapPw); InitialLdapContext ctx = (InitialLdapContext) jlc.getLdapContext(at.getPrincipal(), at.getCredentials()); SearchResult result = searchUnique(sf, ctx); Attributes attrs = result.getAttributes(); username = "******" + attrs.get("cn").get(0) + ",ou=gateways," + MessagingServletConfig.ldapBaseDn; ctx.close(); } catch (IllegalStateException | NamingException e) { e.printStackTrace(); log.warn(username + "not found in directory"); } return createToken(username, password, request, response); }
/* (non-Javadoc) * @see org.apache.shiro.authc.credential.CredentialsMatcher#doCredentialsMatch(org.apache.shiro.authc.AuthenticationToken, org.apache.shiro.authc.AuthenticationInfo) */ @Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { if (token instanceof AutologinToken) { log.debug("Auto-logging in {}", token.getPrincipal()); return true; } if (token.getCredentials() == null) { log.warn("Rejecting null token credentials for {}", token.getPrincipal()); return false; } if (info.getCredentials() == null) { log.warn("Rejecting null stored credentials for {}", info.getPrincipals()); return false; } final String host = token instanceof HostAuthenticationToken ? ((HostAuthenticationToken) token).getHost() : null; final String passwordToken = String.valueOf((char[]) token.getCredentials()); final String userPassword = info.getCredentials().toString(); final Matcher matcher = passwordPattern.matcher(userPassword); if (matcher.matches()) { final String algorithm = matcher.group(1); final String encodedBase64 = matcher.group(2); switch (algorithm) { case "SSHA": final byte[] encoded = Base64.decodeBase64(encodedBase64); log.trace("Decoded {} into {} bytes", encodedBase64, encoded.length); if (encoded.length < 21) { log.error( "Encoded length must be at least 21 bytes, 20-byte password and at least 1-byte salt, for {}", info.getPrincipals()); return false; } final byte[] digest = Arrays.copyOf(encoded, 20); final byte[] salt = Arrays.copyOfRange(encoded, 20, encoded.length); byte[] digestToken = HashedPasswordUtils.calculateSsha(passwordToken, salt); boolean sshaMatches = Arrays.equals(digestToken, digest); log.debug( "Matching credentials for {} host {} using SSHA: {}", token.getPrincipal(), host, sshaMatches); return sshaMatches; case "PLAIN": boolean plainMatches = encodedBase64.equals(passwordToken); log.debug( "Matching credentials for {} host {} using PLAIN: {}", token.getPrincipal(), host, plainMatches); return plainMatches; default: log.error("Unknown password algorithm {} for {}", algorithm, info.getPrincipals()); return false; } } else if (userPassword.startsWith("$")) { final BCryptPasswordService bCryptPasswordService = new BCryptPasswordService(); return bCryptPasswordService.passwordsMatch(passwordToken, userPassword); } else { log.error("Unknown password syntax for {}", info.getPrincipals()); return false; } }