admin管理员组

文章数量:1296440

I recently switched to Rails 4 and the security requirements no longer seem to allow the use of regular expressions in the style of /^..$/. The error states that regular expressions should instead be written in the style of /\A..\z/. Making this change seems to resolve all of my server side validation issues, but unfortunately it also broke all of my client side validation in javascript.

A simple example. I want to validate a username to be letters, number, or periods.

The old regex looked like /^[0-9a-zA-Z.]+$/ and worked both server side (Rails 3.x) and client side

new RegExp( /^[0-9a-zA-Z.]+$/ ).test('myuser.name') = true

The new regex looks like /\A[0-9a-zA-Z.]+\z/ and works server side but fails client side

new RegExp( /\A[0-9a-zA-Z.]+\z/ ).test('myser.name') = false

So I'm clearly doing something wrong, but I can't seem to find any explanations. I checked that \A..\z are valid regex to make sure that its not some Rails-specific hack and it seems to be legit.

Any ideas?

I recently switched to Rails 4 and the security requirements no longer seem to allow the use of regular expressions in the style of /^..$/. The error states that regular expressions should instead be written in the style of /\A..\z/. Making this change seems to resolve all of my server side validation issues, but unfortunately it also broke all of my client side validation in javascript.

A simple example. I want to validate a username to be letters, number, or periods.

The old regex looked like /^[0-9a-zA-Z.]+$/ and worked both server side (Rails 3.x) and client side

new RegExp( /^[0-9a-zA-Z.]+$/ ).test('myuser.name') = true

The new regex looks like /\A[0-9a-zA-Z.]+\z/ and works server side but fails client side

new RegExp( /\A[0-9a-zA-Z.]+\z/ ).test('myser.name') = false

So I'm clearly doing something wrong, but I can't seem to find any explanations. I checked that \A..\z are valid regex to make sure that its not some Rails-specific hack and it seems to be legit.

Any ideas?

Share Improve this question asked Feb 14, 2014 at 17:53 R. YanchuleffR. Yanchuleff 3231 silver badge15 bronze badges 1
  • MDN Regular Expressions – epascarello Commented Feb 14, 2014 at 18:11
Add a ment  | 

3 Answers 3

Reset to default 10

JavaScript does not support \A or \z in its RegExp.

Here's some raw data, first for JavaScript:

var a = "hello\nworld"
(/^world/).test(a) // false
(/^world/m).test(a) // true
(/hello$/).test(a) // false
(/hello$/m).test(a) // true

Next, for ruby:

a = "hello\nworld"
a.match(/^world/) # => #<MatchData "world">
a.match(/\Aworld/) # => nil
a.match(/hello$/) # => #<MatchData "hello">
a.match(/hello\z/) # => nil

From this, we see that ruby's \A and \z are equivalent to JavaScript's ^ and $ as long as you don't use the multiline m modifier. If you are concerned about the input having multiple lines, you're simply going to have to translate your regular expressions between these two languages with respect to these matching characters.

  • (?<![\r\n])^ emulates \A, match absolute string start.

  • $(?![\r\n]) emulates \z, match absolute string end. (source)

  • (?=[\r\n]?$(?![\r\n])) emulates \Z, match string end (before final newline if present).

If all of your line endings are \n, you can simplify the above to:

  • \A: (?<!\n)^

  • \z: $(?!\n)

  • \Z: (?=\n?$(?!\n))

Note: JavaScript has always supported lookahead (used for \z & \Z emulation above), but lookbehind (used for \A emulation above) support is newer, and still limited due to Safari / WebKit, see caniuse. and bugs.webkit for details. Node.js has had lookbehind support since v9.

As a workaround for \A\a \Z\z lack of support, you can add a "sentinel" character (or characters) to the end of the input string.

Please, note that:

  1. the sentinel character(s) should be something which very low chances of being used in the input string.
  2. should not be used in sensitive stuff (such as user verification or something) since a workaround like this can be easily exploitable.

In this specific case, since only [0-9a-zA-Z.] are allowed, something like ¨ or ~ is ok.

Example:

let inputString = 'myuser.name';
inputString = '¨0' + inputString + '¨1';
let result = new RegExp( /¨0[0-9a-zA-Z.]+(?=¨1)/ ).test(inputString);
inputString.replace(/^¨0/, '').replace(/¨1$/, '');

If you're worried that, for some reason, the input string might have the selected characters you're using, you can escape them.

本文标签: javascriptRegExp A z doesnt workbut thats what Rails 4 requiresStack Overflow