【问题标题】:How to prevent infinite retries - Apache Shiro RESTful service如何防止无限重试 - Apache Shiro RESTful 服务
【发布时间】:2018-08-18 08:03:30
【问题描述】:

目标
我正在使用 RESTEasy 框架设置一个 RESTful 网络服务。为了安全起见,我使用 Apache Shiro。我希望我的 api 停止接受请求或超时登录过多的人。

问题
每当我使用浏览器(chrome)访问某个 URL 时,我都可以尝试无限次登录。允许这样做似乎是一个非常糟糕的主意。作为一项措施,我确保记住登录尝试的次数,因为用户在 3 次后无法登录。但是,通过蛮力攻击,您仍然可以阻止所有用户登录。我想要一个更通用的解决方案。

Shiro.ini

[main]
# We store users and passwords inside the realm.
myRealm = com.myproject.shiro.DatabaseRealm
sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager
securityManager.sessionManager = $sessionManager
cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
securityManager.cacheManager = $cacheManager

[urls]
/api/version = anon
/api/** = authcBasic

数据库领域

public class DatabaseRealm extends AuthorizingRealm {

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // No clue what to do with this functin. I only use authentication and not authorization, so probably just nothing.
        return null;
    }

    /**
     * Check if the user inputted is valid. The user can login if holds:
     * 1. Password is correct. (if not, nrOfLogonAttempts++)
     * 2. LogonUser.nrOfLogonAttemps is less than 3
     * 3. LogonUser.dateEndValid is null or >= today.
     * @param authenticationToken Token with basic information.
     * @return SimpleAuthenticationInfo
     * @throws AuthenticationException Whenever the user cannot login.
     */
    @SuppressWarnings("ConstantConditions")
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
            throws UnknownAccountException, IncorrectCredentialsException, LockedAccountException, ExpiredCredentialsException {
        // Connect with the database.
        DbContext context = null;
        try {
            context = DbContextUtil.getContextFromTomcat();
            // Lookup user in the database.
            LogonUserMyDao logonUserMyDao = new LogonUserMyDao(context);
            LogonuserPojo logonuserPojo = logonUserMyDao.fetchOneByUsername(((UsernamePasswordToken) authenticationToken).getUsername());
            if (logonuserPojo == null) {
                throw new UnknownAccountException("Could not find user.");
            }

            // Check password
            String plainTextPassword = new String(((UsernamePasswordToken) authenticationToken).getPassword());
            if (!BCryptUtil.checkPassword(plainTextPassword, logonuserPojo.getPassword())) {
                // We will note this event.
                logonuserPojo.setNroflogonattempts(logonuserPojo.getNroflogonattempts() + 1);
                logonUserMyDao.update(logonuserPojo);
                context.commit();
                throw new IncorrectCredentialsException("Incorrect password.");
            }

            // Check nrOfLogonAttempts
            if (logonuserPojo.getNroflogonattempts() >= 2) {
                throw new LockedAccountException("Cannot login anymore.");
            }

            // Check date
            if (logonuserPojo.getDateendvalid() != null && DateTimeUtil.isBeforeToday(logonuserPojo.getDateendvalid())) {
                throw new ExpiredCredentialsException("Account is expired.");
            }

            // User is valid, so return some info.
            return new SimpleAuthenticationInfo(logonuserPojo.getUsername(), plainTextPassword, getClass().getName());
        } catch (SQLException e) {
            MyLogger.logError("Could not connect to user database.", e);
            throw new AuthenticationException("Could not connect to databse.");
        } finally {
            if (context != null) {
                try {
                    context.getConnection().close();
                } catch (SQLException e) {
                    MyLogger.logError("Could not close connection", e);
                }
            }
        }
    }
}

【问题讨论】:

    标签: rest security tomcat shiro


    【解决方案1】:

    您是否正在寻找更通用的 DDOS 保护?根据您的应用程序运行的位置(例如 AWS Shield),有一些选项可供选择。

    您还可以通过以下方式阻止连接到达您的数据库:https://github.com/iTransformers/ddos-servlet-filter(但是,这仍然需要在您的应用程序中处理请求)

    在 Shiro 方面,计算您的尝试次数并不是一个坏主意,但您需要注意用户管理方面的事情(用户如何解锁,支持请求?等待 30 分钟?)而不是记录失败,您可能只想记录/审核所有尝试(当然不包括实际密码)。选择支持电话或n 分钟窗口,这可能有助于提供一些支持背景或简单的查询。

    【讨论】:

    • 感谢您的回答!我真的很喜欢你最后一段的建议。它让我深思。我不是在寻找一般的 DDOS 保护,而是真正的安全保护。
    猜你喜欢
    • 2011-07-20
    • 2013-12-29
    • 1970-01-01
    • 2020-12-10
    • 2014-07-17
    • 1970-01-01
    • 2011-02-27
    • 2015-01-13
    • 1970-01-01
    相关资源
    最近更新 更多