1

I'm working on a project that's left me stumped, hoping someone out there might have some interesting input. I see there are several gems available for obfuscation of urls, but they seem to stop at the slug level instead of the controller level - i.e. www.foo.com/mycontroller/8sZ16lp. I'm looking for a method to produce something along the lines of www.foo.com/8asd31Ud, dropping the controller name. I checked the docs of the obsufacate_id gem, but it doesn't appear to go that far.

To give more background - I'm really hoping to have www.foo.com/mycontroller/15/edit = www.foo.com/95Ali32

PSCampbell
  • 858
  • 9
  • 27
  • The name in the URL references the controller, not the model. – trosborn Feb 03 '15 at 01:04
  • It's been a long day, I fixed it. – PSCampbell Feb 03 '15 at 01:10
  • No worries :) Also IDK what your background in infosec is, but you may want to read up on security by obscurity before you commit a lot of time to this: https://www.owasp.org/index.php/Avoid_security_by_obscurity – trosborn Feb 03 '15 at 01:33
  • Limited for sure, but I'm securing all other functions of the application - I just need to edit function to be able to be updated by a non-registered user. I looked into a few other methods, mostly calling a base64 string from the associated table, but because I have several models I need to cover, I'm beginning to wonder if it's not better to go at it from this angle. – PSCampbell Feb 03 '15 at 02:20

1 Answers1

0

As this doesn't match the convention of rails RESTful URL's my guess is you'll likely just need to write your own routes and maybe more. Out of curiosity, how would you envision that the system knows what type of object to load with "95Ali32"? This might be better to build with Sinatra or something that gives you more control over the routing and less convention.

Here's one possible approach that uses a table with your slugs that maps to type and object id:

# migration
create_table :slugs do |t|
  t.string :object_type, :null => false
  t.string :object_id, :null => false
  t.string :slug
  t.timestamps
end

# models
class Slugs < ActiveRecord::Base
  belongs_to :object, :polymorhic => true
end

class AModel < ActiveRecord::Base
  has_one :slug, :as => :owner
end

# routes.rb
# note that anything else should go above this because this will catch all other URL's
get '*slug', to: 'slugs#show'

# controller
class SlugsController < ApplicationController
  def show
    @object = Slug.where(slug: params[:slug])
    raise ActiveRecord::NotFound.new unless @object
    render @object.kind
  end
end

You would then need to build views for each type of object. See this related question


Update

Here's another idea. How obscure do you need the slug? What if each model has a known code and then the ID is encoded some way and appended to the model code? Then you could do something much simpler in the code using routes that are preconfigured:

# You could generate this too, or just hard-code them
prefixes = ['8sZ', '95Ali']
[:a_model, :another_model].each do |model|
  match "#{prefixes.pop}:id", :controller => model.to_s.underscore.pluralize, :action => :show, :as => model
end 

This would give you routes like these

/8sZ1 #=> AModelsController#show(:id => 1)
/95Ali341 #=> AModelsController#show(:id => 341)

You could take this another level and use friendly_id to generate slugs for the model ID's. Or use UUID's instead of integer ID's (supported by PostgreSQL).

Community
  • 1
  • 1
jwadsack
  • 5,708
  • 2
  • 40
  • 50
  • "Out of curiosity, how would you envision that the system knows what type of object to load with "95Ali32"?" - that's what I can't wrap my head around.. I was thinking if it were a simple encrypt/decrypt method, that might work - foo.com/controller/mycoolentry =>foo.com/somebase64code/littlemorecodehere – PSCampbell Feb 03 '15 at 02:20
  • Ok. Well in the solution I suggested above, I'm using an STI relationship so that the Slug record stores both the id and the type of the associated model. Your encryption/decryption might work as well, as long as you use a 2-way encryption and not just a hash. This makes me think of URL shorteners, and there's a gem that does basically what I suggested above. https://github.com/jpmcgrath/shortener However, not that does a redirect I think is something you were trying to avoid. – jwadsack Feb 04 '15 at 00:59