【问题标题】:How can authenticate user by only ip address in spring security?spring security中如何仅通过IP地址对用户进行身份验证?
【发布时间】:2016-11-13 05:33:26
【问题描述】:

我与用户有一张桌子。此表中有“ip_address”列。

我有服务器 - java 服务器 我在 Spring Boot 上有网络应用程序。

Spring boot 通过 rest 与 java server 通信。

我需要通过ip实现系统中的用户身份验证。 Whem 用户打开网页 - Spring Boot 应用程序获取 remoteIpAddress(String ipAddress = request.getRemoteAddr();) 并将其传递给 url 中的 java 服务器。 java 服务器在用户表中的 db 中检查此 ip,如果用户可以登录,则将此用户返回到 spring boot 应用程序。

我想通过 Spring Security 实现这一点。但是当我打开网页时,在浏览器中打开了输入登录名和密码的对话框窗口。但我不需要登录名和密码。如果用户不为空,我需要 - 授予对页面的访问权限并保存用户。

如果我输入登录名和密码并按“确定”按钮,我会转到我的IPAddressBasedAuthenticationProvider

@Component
public class IPAddressBasedAuthenticationProvider implements AuthenticationProvider {
    @Autowired
    private HttpServletRequest request;
    @Autowired
    AuthService authService;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String ipAddress = request.getRemoteAddr();
        AuthLkUser authLkUserByIp = authService.getAuthLkUserByIp(ipAddress);

        if (authLkUserByIp == null) return null;

        boolean b = authService.checkAuthLkUser(authLkUserByIp);
        if (b) return null;
        final List<GrantedAuthority> grantedAuths = new ArrayList<>();
        GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_ADMIN");
        grantedAuths.add(grantedAuthority);
        UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(authentication.getName(), authentication.getCredentials(), grantedAuths);
        result.setDetails(authentication.getDetails());
        return result;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return true;
    }
}

在此类中将用户保存到会话中。之后,当我打开网页时,我不需要输入登录名和密码。它包含在会话中。但是我的网页没有打开错误

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.
Mon Jul 11 14:27:59 ALMT 2016
There was an unexpected error (type=Forbidden, status=403).
Access is denied

【问题讨论】:

  • 无配置,无堆栈跟踪。你真的调试过你的代码吗?另外恕我直言,注入HttpServletRequest 来获取您需要的信息是一个糟糕的主意。它是在Authentication 上设置的WebAuthenticatioNDetails 的一部分,请改用它。也不确定基于 IP 地址的身份验证是否是一个好主意,大公司呢,由于每个人都使用代理,他们通常只有一个外部 IP 地址。

标签: java spring spring-security


【解决方案1】:

对于使用嵌入式 Apache Tomcat 容器运行的 Spring Boot 应用程序,您可以使用 Apache Tomcat 中的 org.apache.catalina.filters.RemoteAddrFilter。

 @Bean
 public FilterRegistrationBean remoteAddressFilter() {
  FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
  RemoteAddrFilter filter = new RemoteAddrFilter();
 // filter.setAllow("127.0.0.1");
  filter.setAllow("127\\.0\\.0\\.1");
  filterRegistrationBean.setFilter(filter);
  filterRegistrationBean.addUrlPatterns("/gs/serving-web-content/testParameters");
  return filterRegistrationBean;
 }

allow : 远程的正则表达式(使用 java.util.regex) 与客户端的 IP 地址进行比较。如果指定了此属性, 远程地址必须匹配才能接受此请求。如果这 未指定属性,所有请求都将被接受,除非 远程地址匹配拒绝模式。

你可以参考这篇文章-How do I restrict access to my application by IP address?

【讨论】:

    【解决方案2】:

    您可以使用 Spring 提供的基于表达式的访问控制。要保护单个 URL,您可以执行以下操作:

    <http use-expressions="true">
        <intercept-url pattern="/admin*"
            access="hasRole('admin') and hasIpAddress('192.168.1.0/24')"/>
        ...
      </http>
    

    如果他有角色管理员并且他的IP地址是xxx.xxx.x.x,那么你创建的表达式是允许的。所以你正在寻找hasIpAddress。 更多关于基于表达式的访问控制在他们的docs

    如果您想为 Spring Boot 创建此限制并且如果您使用的是 Apache Tomcat,那么您可以启用 Servlet 过滤器(here 是描述),然后您可以启用 远程地址过滤器 然后设置您要允许的地址。有关此过滤器的更多信息,请参见 Apache Tomcat docs

    另外一种选择是,如果您将使用 Spring Security。 There isWebAuthenticationDetails 提供方法 getRemoteAddress()

    【讨论】:

    • 我已经看到了这个解决方案,但我不知道在哪里写这个?我没有 web.xml
    • 你没有 web.xml?为您的问题添加更多配置和项目结构。
    • 对不起,我只看到了弹簧,没有看到弹簧靴
    • 你在 apache tomcat 上运行吗?
    • 好的,然后检查我的编辑。您应该使用 apache tomcat 中的远程地址过滤器类
    猜你喜欢
    • 2019-12-26
    • 2012-03-06
    • 2013-02-23
    • 1970-01-01
    • 2020-04-16
    • 2013-06-12
    • 2014-08-24
    • 1970-01-01
    • 2011-08-12
    相关资源
    最近更新 更多