1

我正在做一个简单的Intranet应用程序,虽然有一些用户,但一般人员不需要登录。他们应该能够从任何计算机访问 Intranet 并在不登录的情况下访问他们需要的内容。

我们的一些用户是远程的,他们应该能够以相同的方式进行交互。

我想要实现的是以下内容;无需登录即可直接进入根 URL 的 IP 和子网列表(管理员仍然可以登录)。任何不在白名单 IP 和子网列表中的访问者都应该看到静态访问被拒绝页面。在该页面上应该是一个登录链接。一旦登录,他们就可以与 Intranet 交互,就像他们在我们的白名单子网中一样。一旦他们注销,他们就会再次看到拒绝访问页面。

我的应用程序控制器中有以下代码:

class ApplicationController < ActionController::Base
  before_filter :protect
  protect_from_forgery
  private  

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
    rescue ActiveRecord::RecordNotFound
  end

  helper_method :current_user

  def authorized?
    not current_user.nil?
  end

  def authorize
    redirect_to login_url, alert: "Not authorized" unless authorized?
  end

  def authorize_admin
    redirect_to login_url, alert: "Not authorized" unless authorized? && current_user.admin?
  end

  def protect
    @ips = ['127.0.0.1','123.123.123.12','192.168.5.0/24']
    allowed = false
      bremote_ip = 0
      request.remote_ip.split('.').each { |x| bremote_ip = (bremote_ip << 8) + x.to_i }
      @ips.each do |ipstring|
        ip, mask = ipstring.split '/'
        mask = mask ? mask.to_i : 32
        bip = 0
        ip.split('.').each { |x| bip = (bip << 8) + x.to_i }
        bmask = ((1 << mask) - 1) << (32 - mask)
        if bip & bmask == bremote_ip & bmask
          allowed = true
          break
        end
    end

    if not allowed
       render :template => "static/protect", :layout => "static"
       return
    end
  end

end

任何有关如何实现这一目标的指针将不胜感激。谢谢!

4

1 回答 1

3

来自:Rails 3 - 通过路由将 IP 列入白名单

使用netaddr宝石:

before_filter :protect

def protect
      @ips = []
      @ips << NetAddr::CIDR.create('127.0.0.0/8')
      @ips << NetAddr::CIDR.create('192.168.5.0/24')
      @ips << NetAddr::CIDR.create('123.123.123.12')
      valid = @ips.select {|cidr| cidr.contains?(request.remote_ip) }
      if valid.empty? and !authorized?
        authorize
        return
      end
end

编辑

在这种情况下,上面的示例只是跳过了静态保护页面并将用户重定向到登录页面。我不明白中间静态页面的必要性?

注意:为避免“重定向过多”错误,您可以:exceptbefore_filter语句中添加一个。或者,如果您使用的是 Devise,请将其添加到config/application.rb

# In config/application.rb
module YourAppNameHere
  class Application < Rails::Application
  # Whatever else is already here...

    # The part to add
    config.to_prepare do
      Devise::SessionsController.skip_before_filter :protect
    end
  end
end
于 2012-10-21T13:43:44.450 回答