I am a Java programmer mostly, and it's actually amazing that we don't have to worry about a lot of security concerns that php or even rails developers have to worry about. We have to worry about them, but I think our job is actually a lot easier. You just use Java (already big bonus points there) and use Spring with Spring security... and you're basically done. Java and servlets are actually really good in this respect.
Now that I'm working in Rails, I think the biggest security concerns that I am the most scared of are parameters - both in the ones that are coming from the controllers (since they dynamic hashes, unlike in SpringMVC) and having to include more hidden values in forms.
But that got me thinking - you really have to be careful what you accept when you create new models or even update models. If you just blindly pass in parameters to your models, bad things can happen. In fact, things like the user role and stuff could be changed if you're not too careful.
It's almost like I want to write the setter code by hand to make sure it's not overwriting something that it shouldn't. And even if there's a framework mechanism to handle this... I would still want to test every risky model attribute just to be extra sure that it won't get overwritten on a create and on an update.
As much as Java gets a bad rep about productivity, it feels like it handles this stuff a lot better.
Anyway, my question is - what is the best resource/tips/advice for dealing with common security pitfalls/concerns/gotchas using rails - especially geared towards a Java/Spring developer who got used to working in a more stateful environment.
Even better, what would be a good checklist to go through every once in awhile?
And last, what tests would you recommend to make sure things are solid?
At least for your concern about assigning data to your model objects without proper checking, look into the attr_accessible declaration; it allows only specified attributes to be assigned via the bulk assignment:
user = User.new(params[:user])
user.approved = params[:user][:approved]
user.role = params[:user][:role]
You might find the entire 27th chapter of the Ruby on Rails 3rd edition book useful. (I haven't updated my 4th Edition book yet, not sure which chapter to recommend from the newer book. :)
I don't use ActiveRecord (I use DataMapper), but as a rule, I never do mass-assignment and I always expressly pass only the attributes I want to change. Rails 3 defaults to escaping all content in your views, unless you expressly output that data raw into into the .erb.
Also, it really bugs me that ActiveRecord doesn't help you out very much if you need to drop down to using SQL for something. You have to escape input yourself, which can expose you to the risk of human error allowing arbitrary SQL to be executed in your queries. DataMapper's underlying DataObjects connection supports prepared statements out of the box and in fact, it would actually require more work to avoid using them.
Rails 3 does have CSRF protection turn on by default too. It also makes session cookies HTTP-only by default, which makes them harder to steal via JavaScript.
I actually think, aside from Rails encouraging the use of mass-assignment, you're pretty well-covered for security.
Related
I'm having a hard time wrapping my head around Rails' MVC system and its relationship to Ruby classes. In Rails, it feels like objects go out the window and are replaced by databases.
I'm working on an interview question right now and it requires me to create a website that accepts HTTP requests and returns responses. I'm not super familiar with JS and I like Ruby a lot so I've been using Rails. But I feel so limited by the database... it feels like things that I could do so easily in Ruby (e.g., look through a hash of objects and filter by multiple constraints until I got what I wanted) are so much more difficult with a database.
The interview question says I don't need to use a durable data store, but that seems like a big no-no in Rails. Does anyone have advice for how to change my mindset around this? (Or, in the short term, recommendations for other easy-to-use tools?)
BTW - I know this may beg the question, "why are you interviewing if you don't know this stuff?" It's an internship and I'm just trying to start interviewing as much as possible so I get used to the process.
But I feel so limited by the database... it feels like things that I could do so easily in Ruby (e.g., look through a hash of objects and filter by multiple constraints until I got what I wanted) are so much more difficult with a database.
Working with databases is challenging since SQL is a completely different paradigm. Instead of being object oriented SQL is based on tables and relational algebra.
Everyone finds it easier to hack out loops and create if/else constructs to munge data as a beginner. But its not really a viable solution at scale. Any time you spend learning SQL will pay off immensely in the future.
I'm having a hard time wrapping my head around Rails' MVC system and its relationship to Ruby classes. In Rails, it feels like objects go out the window and are replaced by databases.
This doesn't really have that much do with Rails or MVC. Its rather ActiveRecord which is the object relational mapper (ORM) which is built into Rails by default.
In comparison with other ORM's ActiveRecord has a lot of magic. It reads your table definitions from the database and automatically sets up attributes - in other ORMs you do this explicitly in your model classes, a repository class, XML files or annotations. This magic is great for productivity but can be very difficult to wrap your head around as a beginner.
ActiveRecord is still very much an object oriented design - just with more metaprogramming then you may be used to.
The interview question says I don't need to use a durable data store,
but that seems like a big no-no in Rails.
This is a misconception. Rails is a very modular framework and can be used without ActiveRecord, with other object relational mappers (or object-document mappers) or even without any storage at all.
Models are also are not necissarily even persisted at all. They are just objects that encompass the buisness logic of your application.
Most beginner guides start with ActiveRecord as an overwhelming majority web applications use a SQL database*.
I agree that this is probably one of the hardest things newbies face in Rails. In the Rails guide, models are almost always Active Record models (aka map to a database table). However, it's totally normal that not all of your models are Active Record models and / or need to be persisted. I think the term you're missing are Plain Old Ruby Objects (PORO) and Active Model.
A PORO could be anything from something super simple, a mapping to an API or composing several other (ActiveRecords) models together.
For example, you could have a versions controller which displays the latest version of your web app. The version would be determined by reading the SHA from the git repository, file or env variable. So it would never be persisted in the database.
class Version
def self.from_git
new(`git rev-parse HEAD`)
end
def initialize(name)
#name = name
end
def to_s
#name
end
end
class VersionsController
def show
#version = Version.from_git
end
end
Here are some links you might find useful
https://www.codewithjason.com/code-without-service-objects/
https://www.oreilly.com/library/view/build-chatbot-interactions/9781680507089/f_0047.xhtml
https://thecodest.co/blog/hi-im-poro-2/
https://www.toptal.com/ruby-on-rails/decoupling-rails-components
https://guides.rubyonrails.org/active_model_basics.html
https://www.codewithjason.com/extracting-tidy-poro-messy-active-record-model/
I need to generate xml from a model and send it to a web service on model save.
I'm sure this is a common case and should be straight forward. Just create a job on after_save callback that generates the xml and sends it to the endpoint.
Since I'm new to Ruby on Rails I'm not to sure how to handle this though. My questions are more about code organization. It's not unlikely that this api connection will be discontinued in the future so I need a clean modular way to get rid of it. Would it be best practice/convention to put this in a separate gem? Can gems actually add jobs to an existing rails queue? Can gems create migrations on install? I'll probably need to add a model to keep track of the api sync. How about dropping a table on gem uninstall? Or should I not use a gem for this at all?
I realize these are broad and basic Ruby on Rails questions but I'm kind of drowning in documentation. I'm just hoping for some examples and/or advice and maybe some pointers to relevant documentation. Thanks.
Gem installs/uninstalls are unrelated to apps, they live on different level and do not khow anything about your app code, db and so on unless they are loaded.
Gems for rails can provide rake tasks and/or generators, for example you can look into devise gem structure on how it does this.
But i'd advise against moving code to a gem before you know you have to, like for example when you need to reuse it in different project.
To reuse code inside single project - use mixins/concerns
In general:
don't make it a gem
it's an unnecessary world of pain, pretty much always,
never make anything a gem unless you intend to use it in the same way in 3+ applications
don't extract it into a concern either,
it doesn't seem very likely that you'll do the same operation on multiple models, code reuse seems to not be an issue here and you can actually reuse code more efficiently using service classes too
a lot of experienced Rails programmers regard this practice as concerning, forgive the pun. It seems this view is not shared by the Rails development team, but at least from my experience writing service classes seems like unnecessary complexity until your project grows enough and then you need to refactor a BUNCH of stuff and you realize you would have been better off ditching concerns from the start
use a service class instead and delegate the necessary methods to it from the model
this will leave you with a clean interface to extract later and will also allow you to use dependency injection if you need to mock your XML service for tests
don't tie API requests to model callbacks, there's usually just 2-3 places where you need to do something with the API and a bunch of other cases where that may not be the case, imagine:
tests,
or if you get a requirement to implement cache column,
or a "number of visits" column
or a gem like Paperclip that thought that it wanted to add something to the model but changed his mind and instead of that just touched updated_at
or any such trickery which will make you a grandiose API spammer and a sufferer of VERRRRY slow database updates
if you DO tie API requests to model callbacks,
then you better make sure that error handling is done properly and that timeouts etc don't rollback or delay your DB operation,
best way from my experience is to run these things through ActiveJob + one of the backends (though obviously not the :inline backend and ideally one of the backends which don't use your main database and allow asynchronous job submission - sidekiq comes to mind as a candidate)
I'm just starting out in Rails and there's a lot I still need to learn so I'm likely to be on Stackoverflow more often than normal asking beginner Rails / Ruby questions.
I'm just trying to figure out how Helpers work in Rails. From what I've seen so far, Helpers are intended to be used with Views and not so much with your Controllers.
However I would like to make a simple function that will validate the user input given in params (check if certain params are defined and optionally check if their value is valid).
Can anyone explain to me what would be the best way of implementing this? (Keeping in mind that I will want to use this in many different controllers so it should be globally available.)
I also noticed that by default Rails does not generate a lib folder in the main application folder. Are developers to place their libs outside the app folder in the main folder, or does Rails use libraries differently?
With regards to your validation issue, it depends on what you are validating.
If the data makes up objects from your problem domain, also known as models, then you should use the built in validators from ActiveModel. This is probably what you should do, but its hard to say without knowing the exact problem. See the Rails Guides on Validations. You can tell if this is the case by asking yourself if the data that needs validation will be stored after you get it. If so, its most definitely a model. An example of this kind of data would be the title and text fields of a blog post being sent to Rails from a browser form.
If the data is something tertiary to your models, or specific to presentation, then you should be fine using helpers. You noticed that helpers are used mostly in the views, and although this is true, theres nothing stopping you from using them in the controllers, you just have to declare that you will use them using the ActiveController#helper method. Inside the ApplicationController class, a lot of devs will put helper :all to just include all the helpers in all the controllers. Once the code has been required once, it doesn't really incur that big a performance hit.
Do note that almost all incoming data can be modeled using a model. A big school of thought in the Rails world subscribes to the Fat Model idea. People say that putting as much code as possible in the model and as little in the controller as possible separates concerns properly and leads to more maintainable code. This suggests that even if you don't think the incoming data is modelable (in the sense that you can create a model to represent it), you should try to make it a model and encapsulate the logic around validating it. However, you may find that making a helper function is faster, and either will work.
Your notion of validating user input is a good one. I get the feeling that as you are new to Rails you are used to doing these things yourself, but that doesn't quite apply here. In the Rails world, a lot of the common stuff like validations is handled by the framework. You don't have to check for presence in the params array, instead you call validates_presence_of on the model and let Rails spit the error out to the user. It makes things easier in the long run if you let the framework do what it is designed to.
With regards to your question about the lib folder, it doesn't really matter. You can put miscellaneous support files and libraries in the lib folder in the root directory and they will be available for use in your application (the files in the app folder). You can also choose to abstract your code into a plugin or a gem and include it that way, which a lot of people opt to do. My suggestion for this would be to read up on the notion of gems and plugins before diving in.
Want you want is probably a custom validator (in Rails3):
http://railscasts.com/episodes/211-validations-in-rails-3
You can either add libs in a lib folder you create, or add them to config/initializers in a file you add. Files in the initializers directory are automatically loaded by Rails.
I have been spending some time creating what I called a framework.
It was aimed at the creation of quiz likes games. It was supposed to have two players syncronized and present them a question to solve, etc.
I would like it to be fully customizable so I tried to develop components that can be put in or out of the pages. In the end the elements became slim ruby methods to add a whole bunch of Javascript and CSS to the pages.
Still the Javascript needs to connect to Ruby so methods supporting it are created but they will only be present when the component is present. Some components depend on one another making everything overly complex.
And after this attempt I wonder, is there is not a better and easier way to make a framework aimed to one kind of application on RoR? Or is the concept flawed or RoR in some way flawed?
Ruby on Rails is a framework on its own accord and is "opinionated software". This means that the writers of Rails looked at what would make most sense for creating a web application to them. Many people support the original developers views and so use Rails for their projects as well.
I think your concept of creating a quiz is a good one, but first you need to understand the rails stack. Depending on what you need exactly, you can create either an engine, plugin or whatever.
What I have seen a lot is that you specify what you need in your controller. (How you do that is up to you). All that information is stored in a class variable and transferred to the view where you can render everything you need with some helpers. The hard part is making it all generic enough to be reusable.
But, maybe Rails isn't the right tool for you. Maybe you need something more lightweight like Merb or even Sinatra.
There is no 'flaw' in Rails. Rails is not the 10**1000-in-one tool Java is. It's a framework that tries to do one way very good in a particular way. I think Rails can be the right tool for you, but you need to be skilled enough to wield the tool :)
what do you recommend?
Authlogic or restful_authentication?
Is it hard, to build the email-activation-step into authlogic
(as far as I know, Authlogic hasn't this feature included).
Actually I'd disagree with fig-gnuton. There are a couple of things that you could do. If you want a basic solution try restful auth but be aware that the generator based approach has significant shortcomings. The main shortcoming is that you are squirting a large gob of code into your application. So when there's an issue you have to patch the code manually or blow away any customisations you've made. Recent versions of restful auth are much better than earlier versions which spewed code left, right and centre but my advice would be where possible leave the user and session code generated by restful auth well alone. For example if you want properties on your User make another object like Person and link the two.
I prefer authlogic because:
It feels like you're more in control.
I appreciate the extent to which authlogic is documented and their example app is pretty useful as a guide too.
Also I've had bother with testing restful_auth apps, not so with authlogic.
Extensions like forgotten password resets, API keys and the like are much less custom code than restful_auth.
And don't forget Clearance, the other kid in the block.
Restful Authentication is crap. It's the kind of thing that gives Rails generators a bad name.
What do I mean by that? The generators that come with Rails are (IMHO) good. They generate a very minimalistic skeletal structure. What they generate is small, easily understood, and easy added to/replaced by your own code as you go. All the complex gnarly pieces are in the Rails libraries, where they belong, not in the generated code.
Restful Authentication, on the other hand, comes with generators that spew out massive amounts of generated code that's hard to work with and hard to maintain. Functionality that should be in a nice library where it can be easily upgrade with each new version of the framework is instead spewed out in generated model and controller code where it'll end up intermixed with your code. It's not scaffolding, it's a mass one way dump of autogenerated code.
Stay away... stay far away....
You're better off with authlogic.
take a look at my reasoning here
http://blog.platform45.com/2009/09/30/user-authentication-with-authlogic
Restful_Auth is a drop-in solution.
Authlogic is great and can do anything restful_auth can do (and more, afaik), but Authlogic is geared to customization, it therefore lacks the generator aspect (by design rather than oversight).
Bottom line, if you're a newbie (sounds like you might be), I'd start with restful_auth.