代码之家  ›  专栏  ›  技术社区  ›  J.Hendrix

我如何验证美国社会保障号码?

  •  38
  • J.Hendrix  · 技术社区  · 17 年前

    有人知道如何改进这个功能吗?我不担心缩短代码,我相信这可以用更好的正则表达式来完成,我更关心正确的逻辑。我很难找到SSN#的文档。我下面使用的大多数规则都来自信贷行业的其他程序员(没有引用任何来源)。

    1. 是否有任何其他规则 你知道吗?

    2. 你知道这些有没有错?

    3. public static bool isSSN(string ssn)
      {
          Regex rxBadSSN = new Regex(@"(\d)\1\1\1\1\1\1\1\1");
      
          //Must be 9 bytes
          if(ssn.Trim().Length != 9)
              return false;
      
          //Must be numeric
          if(!isNumeric(ssn))
              return false;
      
          //Must be less than 772999999
          if( (Int32)Double.Parse(ssn.Substring(0,3)) > 772 )
          {
              //Check for Green Card Temp SSN holders
              // Could be 900700000
              //          900800000
              if(ssn.Substring(0,1) != "9")
                  return false;
      
              if(ssn.Substring(3,1) != "7" && ssn.Substring(3,1) != "8")
                  return false;
          }
      
          //Obviously Fake!
          if(ssn == "123456789")
              return false;
      
          //Try again!
          if(ssn == "123121234")
              return false;
      
          //No single group can have all zeros
          if(ssn.Substring(0,3) == "000")
              return false;
          if(ssn.Substring(3,2) == "00")
              return false;
          if(ssn.Substring(5,4) == "0000")
              return false;
      
          //Check to make sure the SSN number is not repeating
          if (rxBadSSN.IsMatch(ssn))
              return false;
      
          return true;
      }
      
    8 回复  |  直到 6 年前
        1
  •  22
  •   Eric J.    11 年前

    更新

    2011年6月25日,SSA将SSN分配过程更改为“SSN随机化”。[27]SSN随机化通过以下方式影响SSN分配过程:

    它消除了最高组号的重要性,因此,高组列表被及时冻结,可用于验证随机化实施日期之前发布的SSN。 之前未分配的区号已被引入分配,但区号000、666和900999除外。

    新规则

    • 社会保障号码是一个九位数的数字,格式为“AAA-GG-SSSS”。该数字分为三个部分。
    • 中间的两位数字是组号。组号的范围从01到99。
    • 最后四位数字是序列号。它们表示组内从0001到9999的直接数字序列。
    • 一些特殊数字从未被分配:
      • 任何数字组(000-###-####、###-00-###、###-###-000)中的全零数字。
      • 第一个数字组中包含666或900-999(个人纳税人识别号)的数字。
    • SSN used in advertising 使这些数字无效。

    http://en.wikipedia.org/wiki/Social_Security_number#Structure

    之前的回答

    most-complete description 我发现了一个SSN的组成。

        2
  •  16
  •   Pr0methean    8 年前

    截至2011年,SSN完全随机化( http://www.socialsecurity.gov/employer/randomization.html )

    唯一剩下的真正规则是:

    • 不能以900-999开头(尽管个人纳税人识别号在某些情况下可以像SSN一样被临时居民和无证/DACA/DAPA移民使用,但格式相同,确实以9开头)
    • 不能以666开头
    • 必须是9位数字或11位带2个破折号的数字
    • 不能是任何已知的假货;
      • “078051120”--伍尔沃斯钱包惨败
      • “219099999”——社会保障局在广告中使用
        3
  •  14
  •   MaKR    11 年前

    由于验证规则的变化,在初始问题5年后回答 Social Security Administration 。还有一些特定的数字根据此无效 link .

    根据我近2年的回答,我也省略了isNumeric(ssn),因为该字段是一个数字,在调用validate函数之前已经删除了字符。

    // validate social security number with ssn parameter as string
    function validateSSN(ssn) {
      // find area number (1st 3 digits, no longer actually signifies area)
      var area = parseInt(ssn.substring(0, 3));
      return (
        // 9 characters
        ssn.length === 9 &&
        // basic regex
        ssn.match(/^[0-8]{1}[0-9]{2}[0-9]{2}[0-9]{4}/) &&
        // disallow Satan's minions from becoming residents of the US
        area !== 666 &&
        // it's not triple nil
        area !== 0 &&
        // fun fact: some idiot boss put his secretary's ssn in wallets
        // he sold, now it "belongs" to 40000 people
        ssn !== '078051120' &&
        // was used in an ad by the Social Security Administration
        ssn !== '219099999'
      );
    }
    

    根据最新信息,没有其他检查要执行。

        4
  •  11
  •   Zed    17 年前

    这显然是一篇旧文章,但我找到了一些缩短它的方法。根据此链接,还有一些特定的数字要无效: http://www.snopes.com/business/taxes/woolworth.asp

    function validateSSN(ssn) {
        // validate format (no all zeroes, length 9
        if (!ssn.match(/^[1-9][0-9]{2}[1-9][0-9]{1}[1-9][0-9]{3}/)
                || ssn.length!=9) return false;
    
        // validate area number (1st 3 digits)
        var area=parseInt(ssn.substring(0, 3));
        //  standard      railroad numbers (pre-1963)
        if (area>649 && !(area>=700 && area<=728)) return false;
    
        // disallow specific invalid number
        if (ssn=='078051120' || // fun fact: some idiot boss put his
                                // secretary's ssn in wallets he sold,
                                // now this is 40000 people's ssn
            ssn=='219099999' || // was used in an ad by the Social Security
                                // Administration
            ssn=='123456789' || // although valid it's not yet assigned and
                                // you're not likely to meet the person who
                                // will get it
            ssn=='123121234' || // probably is assigned to someone but more
                                // likely to find someone trying to fake a
                                // number (next is same)
            ssn=='321214321' || // all the rest are likely potentially
                                // valid, but most likely these numbers are
                                // abused
            ssn=='111111111' ||
            ssn=='222222222' ||
            ssn=='333333333' ||
            ssn=='444444444' ||
            ssn=='555555555') return false;
    
        return true;
    }
    
        5
  •  3
  •   MaKR    11 年前

    这是我的PHP版本

    /**
     * Validate SSN - must be in format AAA-GG-SSSS or AAAGGSSSS
     *
     * @param $ssn
     * @return bool
     */
    function validate_ssn($ssn) {
    
        $ssnTrimmed = trim($ssn);
    
        // Must be in format AAA-GG-SSSS or AAAGGSSSS
        if ( ! preg_match("/^([0-9]{9}|[0-9]{3}-[0-9]{2}-[0-9]{4})$/", $ssnTrimmed)) {
            return false;
        }
    
        // Split groups into an array
        $ssnFormatted = (strlen($ssnTrimmed) == 9) ? preg_replace("/^([0-9]{3})([0-9]{2})([0-9]{4})$/", "$1-$2-$3", $ssnTrimmed) : $ssnTrimmed;
        $ssn_array = explode('-', $ssnFormatted);
    
        // number groups must follow these rules:
        // * no single group can have all 0's
        // * first group cannot be 666, 900-999
        // * second group must be 01-99
        // * third group must be 0001-9999
    
        foreach ($ssn_array as $group) {
            if ($group == 0) {
                return false;
            }
        }
    
        if ($ssn_array[0] == 666 || $ssn_array[0] > 899) {
            return false;
        }
    
        return true;
    }
    
        6
  •  1
  •   AbcAeffchen    11 年前

    我知道这是一个老问题,但为了其他人寻找答案,我想我应该添加一个快速的javascript函数来检查给定的SSN是否有效。

    function checkSSN() {
        var inputSSN = #YourInput#,
            ssnRegex = new RegExp("^(9[0-9][0-9]|666|000|078051120|219099999|123456789|123121234|321214321)|^([0-8][0-9][0-9]00)|^([0-8][0-9][0-9][0-9][0-9]000)$"),
            repeats = /^(.)\1+$/;
            
        //make sure we have 2 dashes in the input Social Security number
        if( inputSSN.match(/./g).length === 2) {
            //Once we have confirmed that there are the right number of dashes, remove them, and make sure that the resulting string is a number (you may or may not need this logic depending on the format of your input SSN.
            inputSSN = inputSSN.replace(/-/g, "");
    
            if(!isNaN(inputSSN)) {
                //Test the input SSN against our regex to ensure that it doesn't contain any disqualifying combinations.
                if(!ssnRegex.test(inputSSN)) {
                    //Make sure the input SSN isn't just a repeated number
                    if(!repeats.test(inputSSN)) {
                        //If it lands inside of this, we know it's a valid option for a social security number.
                    }
            }   
        }
    }
    

    对于ssnRegex逻辑 :

    第一部分处理SSN是否以数字900-999、666、000或上述已知的取消资格的SSN之一开头。

    ^(9[0-9][0-9]|666|000|078051120|219099999|123456789|123121234|321214321)

    第二部分确保2位数字部分不是00

    ^([0-8][0-9][0-9]00)

    第三部分确保最后一部分不是0000

    ^([0-8][0-9][0-9][0-9][0-9]0000)

        7
  •  1
  •   GuyThreepwood64    9 年前

    随着911事件后社会保障号码的随机化,900系列甚至666中的条目现在都是潜在的有效号码。


    第一组3永远不会是000
    中间的一对永远不会是00
    最后四个永远不会是0000

    您可以通过首先测试来执行一些测试,以确保条目的数值>=1010001[和<1000000000](001-01-0001的ssan似乎是合法分配的最低值)。然后,您可以继续检查位置4和5中的00,以及最后四个位置中的0000。

        8
  •  0
  •   Jesse Szypulski    10 年前

    在Hive中,SSN验证或ITIN验证类似于:

    select case when '078051120' rlike '^(?!1{9}|2{9}|3{9}|4{9}|5{9}|6{9}|7{9}|8{9}|9{9}|219099999|078051120|123456789)(?!666|000|9[0-9]{2})[0-9]{3}(?!00)[0-9]{2}(?!0{4})[0-9]{4}$' then 'SSN' 
         when '078051120' rlike '^9[0-9]{2}(7[0-9]|80|81|82|83|84|85|86|87|88)[0-9]{4}$' then 'ITIN' 
         else 'INVLD'
    end as ssn_flg;
    

    将虚拟“078051120”更改为表的列名。