需要为程序中添加此功能。系统管理可以管理设置此参数,Default值为0,更新大于0,说明启用功能。其实它和用户管理表中的另外一个选项“密码永不过期”相辅相成之后,才能成形一个完整的功能。

 

 

管理员更新“密码过期天数”选项值,如果由大于0的数值更新为0(初始值),数据库触发器会检查用户管理表中的“密码永不过期”选项或“密码过期日期”是否有值,如果条件为真,更新动作终止。

tri_PasswordParameter_Update
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[tri_PasswordParameter_Update] ON [dbo].[PasswordParameter]
FOR UPDATE
AS
BEGIN
    DECLARE @PasswordParameterId TINYINT,@ParameterValue TINYINT
    
    SELECT @PasswordParameterId = [PasswordParameterId] FROM DELETED
    SELECT @ParameterValue = [ParameterValue] FROM INSERTED
    
    IF (@PasswordParameterId = 5 AND @ParameterValue = 0 AND EXISTS(SELECT TOP 1 1 FROM [dbo].[Users] WHERE [PasswordNeverExpires] = 1 OR [PasswordExpirationDate] IS NOT NULL))
    BEGIN
        RAISERROR(N'设置已经生效应用,不能初始化为0。',16,1)
        ROLLBACK TRANSACTION
    END
END

 

用户管理表的“密码过期日期”,是只读字段,不能人为手动更新,方法可以参考:http://www.cnblogs.com/insus/archive/2012/02/08/2342430.html

管理员更新“密码永不过期”选项,如果Enable的话,系统首选去检查密码参数设置的“密码过期天数”是否设值启用。如果没有启用,提示管理员首先设置。如果已经设置,系统会获取此值,并更新“密码过期日期”。如果取消,系统也会更新“密码过期日期”字段,初始化为NULL空。

可以参考下面的触发器:

tri_Users_Update
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO


ALTER TRIGGER [dbo].[tri_Users_Update] 
ON [dbo].[Users]
FOR UPDATE
AS
DECLARE @PasswordExpiration TINYINT = [dbo].[udf_GetPasswordParameterValue](5)
DECLARE @PasswordNeverExpires_N BIT = (SELECT [PasswordNeverExpires] FROM INSERTED)
DECLARE @PasswordNeverExpires_O BIT = (SELECT [PasswordNeverExpires] FROM DELETED)
DECLARE @UsersId INT = (SELECT [UsersId] FROM DELETED)

IF @PasswordNeverExpires_N = 1 AND @PasswordExpiration = 0
BEGIN
    RAISERROR(N'更新密码永不过期选项,先设置密码参数中的密码过期天数,更新操作终止。',16,1)
    ROLLBACK TRANSACTION
END
ELSE
BEGIN
    IF  @PasswordNeverExpires_O = 0 AND @PasswordNeverExpires_N = 1 
        UPDATE [dbo].[Users] SET [PasswordExpirationDate] = DATEADD(day,@PasswordExpiration,CURRENT_TIMESTAMPWHERE [UsersId] = @UsersId
    
    IF @PasswordNeverExpires_O = 1 AND @PasswordNeverExpires_N = 0 
        UPDATE [dbo].[Users] SET [PasswordExpirationDate]  = NULL WHERE [UsersId] = @UsersId
        
    IF UPDATE([PasswordExpirationDate])
    BEGIN
        RAISERROR(N'禁止人为更改密码过期时间,更改操作终止。',16,1)
        ROLLBACK TRANSACTION
    END
END

 

posted @ 2012-02-09 16:42 Insus.NET 阅读(33) 评论(0) 编辑

最近开发SQL想控制某些字段,不能手动直接在SQL 编辑更改,因而想到SQL只读字段功能。

就比如实现的用户锁定时间,以及密码过期时间,这两个字段均是由密码参数相关设置而系统变更,为了不想让人为在数据手动更改它们,产生与策略相违的做法,因此Insus.NET特为此表写了一个更新(UPDATE)触发器,实现让SQL的字段有只读功能。如:

tri_Users_Update
CREATE TRIGGER [dbo].[tri_Users_Update] 
ON [dbo].[Users]
FOR UPDATE
AS    
IF UPDATE([LockoutDate])  --用户锁定时间
BEGIN
    RAISERROR(N'禁止更改密码锁定时间,更改操作终止。',16,1)
    ROLLBACK TRANSACTION
END
    
IF UPDATE([PasswordExpirationDate]--密码过期时间
BEGIN
    RAISERROR(N'禁止更改密码过期时间,更改操作终止。',16,1)
    ROLLBACK TRANSACTION
END

 

posted @ 2012-02-08 12:39 Insus.NET 阅读(82) 评论(2) 编辑

今天分享密码策略的重试次数与登录失败锁定持续的小功能。

软件中,需要一个管理介面,可让系统管理设置相关的参数,这些设置将保存于数据库中,这两个参数初始化为0,如果大于0,说明管理员已经启用此功能。如下:

 

从功能上看,只是涉及至验证用户与登录时需要实现在功能,Insus.NET不想改动太多地方,特别是程序部分,因此Insus.NET只是修改用户登录验证的一个存储过程:

逻辑太约分几步,首先是密码参数表获取上图中两个参数:

View Code
DECLARE @NumberOfRetries TINYINT =  [dbo].[udf_GetPasswordParameterValue](1)
DECLARE @LockoutDuration TINYINT =  [dbo].[udf_GetPasswordParameterValue](2)

 

从用户表中,获取当前登录的用户名的登录失败次数与及锁定时间:

View Code
DECLARE @LoginFailures TINYINT,@LockoutDate DATETIME
SELECT @LoginFailures = [LoginFailures],@LockoutDate = [LockoutDate] FROM [dbo].[Users] WHERE [Account] = @Account

 

宣告一个锁定过期时间,即是锁定时间加上密码参数表设定的密码锁定持续时间

View Code
DECLARE @ExpirationDate DATETIME = DATEADD(minute,@LockoutDuration,@LockoutDate)

 

写一个判断,判断用户是否被锁定,如果用户在锁定期间,用户还不断重次登录,此时不管密码正确与否,均以当前时间更新用户锁定时间。其中有一个SQL日期时间比较自定义函数[dbo].[udf_DateTimeCompare],可以参考:http://www.cnblogs.com/insus/archive/2011/06/24/2089005.html

View Code
IF [dbo].[udf_DateTimeCompare](@ExpirationDate,CURRENT_TIMESTAMP> 0 
BEGIN    
    UPDATE [dbo].[Users] SET [LockoutDate] = CURRENT_TIMESTAMP  WHERE [Account] = @Account
    RAISERROR(N'用户名已被锁定。',16,1)
    RETURN
END

 

 用户在没有锁定情况之下,如果用户名与密码正确,允许用户顺利登录,还在更新锁定时间与登录失败次数字段,初始化为NULL和0。

View Code
IF EXISTS(SELECT TOP 1 1 FROM [dbo].[Users] WHERE [Forbidden] = 0 AND [Account] = @Account AND [Password] = @Password)
BEGIN
    UPDATE [dbo].[Users] SET [LockoutDate] = NULL[LoginFailures] = 0 WHERE [Account] = @Account    
    SELECT [UsersId],[WorkNumber],[Account] FROM [Users] WHERE [Account] = @Account
END

 

如果用户输入的密码不正确

 判断是否设置与启用了用户登录重试次数要求,可以从密码参数表的密码重试次与锁定持续时间均大于0

View Code
IF @NumberOfRetries > 0 AND @LockoutDuration > 0 

 

如果登录失败重试且是最后一次,更新登录失败次数以及锁定时间,反之,仅更新登录失败次数。

View Code
IF @NumberOfRetries - @LoginFailures = 1
            UPDATE [dbo].[Users] SET [LoginFailures] = [LoginFailures] + 1,[LockoutDate] = CURRENT_TIMESTAMP  WHERE [Account] = @Account
        ELSE
            UPDATE [dbo].[Users] SET [LoginFailures] = [LoginFailures] + 1 WHERE [Account] = @Account

 

较完整的存储过程(仅供参考):

usp_Users_LoginVerifyAndGetInfor
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
--
 Author:        Insus.NET
--
 Create date: 2009-04-06
--
 Update date: 2012-02-07
--
 Description:    Verify user login and get infor
--
 =============================================

ALTER PROCEDURE [dbo].[usp_Users_LoginVerifyAndGetInfor]
(
    @Account nvarchar(30),
    @Password nvarchar(30)
)
AS
DECLARE @NumberOfRetries TINYINT =  [dbo].[udf_GetPasswordParameterValue](1)
DECLARE @LockoutDuration TINYINT =  [dbo].[udf_GetPasswordParameterValue](2)

IF NOT EXISTS(SELECT TOP 1 1 FROM [dbo].[Users] WHERE [Account] = @Account)
BEGIN    
    RAISERROR(N'用户名或密码错误。',16,1)
    RETURN
END

IF EXISTS(SELECT TOP 1 1 FROM [dbo].[Users] WHERE [Forbidden] = 1 AND [Account] = @Account)
BEGIN    
    RAISERROR(N'用户名已荒废或被禁用。',16,1)
    RETURN
END

DECLARE @LoginFailures TINYINT,@LockoutDate DATETIME
SELECT @LoginFailures = [LoginFailures],@LockoutDate = [LockoutDate] FROM [dbo].[Users] WHERE [Account] = @Account
DECLARE @ExpirationDate DATETIME = DATEADD(minute,@LockoutDuration,@LockoutDate)

IF [dbo].[udf_DateTimeCompare](@ExpirationDate,CURRENT_TIMESTAMP> 0 
BEGIN    
    UPDATE [dbo].[Users] SET [LockoutDate] = CURRENT_TIMESTAMP  WHERE [Account] = @Account
    RAISERROR(N'用户名已被锁定。',16,1)
    RETURN
END

IF EXISTS(SELECT TOP 1 1 FROM [dbo].[Users] WHERE [Forbidden] = 0 AND [Account] = @Account AND [Password] = @Password)
BEGIN
    UPDATE [dbo].[Users] SET [LockoutDate] = NULL[LoginFailures] = 0 WHERE [Account] = @Account    
    SELECT [UsersId],[WorkNumber],[Account] FROM [Users] WHERE [Account] = @Account
END
ELSE
BEGIN
    IF @NumberOfRetries > 0 AND @LockoutDuration > 0 
    BEGIN
        IF @NumberOfRetries - @LoginFailures = 1
            UPDATE [dbo].[Users] SET [LoginFailures] = [LoginFailures] + 1,[LockoutDate] = CURRENT_TIMESTAMP  WHERE [Account] = @Account
        ELSE
            UPDATE [dbo].[Users] SET [LoginFailures] = [LoginFailures] + 1 WHERE [Account] = @Account
    END
    
    RAISERROR(N'用户名或密码不正确。',16,1)
    RETURN
END

 

posted @ 2012-02-08 09:21 Insus.NET 阅读(54) 评论(0) 编辑

“Hi,我看了你这篇 三个随机产生密码的存储过程 最后一种的写法随机产生密码,觉得很好,并应用在我的程序中,但是上星期老板对我说,要在随机产生的密码带有特殊字符。我再次测试过之后,才发现你的函数产生的密码只是大小写英文字母和数字,并无包含特殊字符,我要怎样改它呢?”

上面全文来自QQ留言。

 

解决你的问题,需要使用上面相同一篇博文的第二种方法相结合,才可以,其实方法还有其它的,下面仅是Insus.NET想到的一种,仅供你参考,有问题,请继续来信,留言或在线讨论:

usp_RandomPassword
ALTER PROCEDURE [dbo].[usp_RandomPassword] 
(
   @Length INT = 8
)
AS
BEGIN  
    DECLARE @RandomPassword  NVARCHAR(MAX= N'',@L INT = 1   
    --下面的变量,你可以自定制需要的特殊字符
    DECLARE @SpecialCharacter NVARCHAR(255= '@#$%&*?'
    WHILE @L <= @Length 
    BEGIN         
       --下面这句,Insus.NET把2改为3。
        DECLARE @R INT = ROUND(RAND() * 30
        SET @RandomPassword = @RandomPassword + CASE @R
        WHEN 0 THEN CHAR(ROUND(RAND() * 9 + 48,0)) 
        WHEN 1 THEN CHAR(ROUND(RAND() * 25 + 65,0)) 
        WHEN 2 THEN CHAR(ROUND(RAND() * 25 + 97,0)) 
        WHEN 3 THEN SUBSTRING(@SpecialCharacterCONVERT(TINYINT,ROUND(RAND() * 6 + 1,0)),1END  --添加此句                                           
        SET @L = @L + 1        
    END
    SELECT @RandomPassword
END

  

posted @ 2012-02-06 11:17 Insus.NET 阅读(98) 评论(0) 编辑

需要为程序加一些功能,如下表,这些设置可让管理员根据自己实际情况设置,缺省值为0不作任限制。

 

由于不是全新开发,而是在现在有程序补充功能,Insus.NET不想在程序作过多更改,只好修改存储过程来实现它们。现下面把实现上图highlight的选项功能分享出来。

保持密码原有记录值,只要管理员设置了密码策略之后,用户更改自己的密码时,就会应用到了新密码策略。

首先写一个获取参数值的自定义函数:

udf_GetPasswordParameterValue
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

-- =============================================
--
 Author:        Insus.NET
--
 Create date: 2012-02-05
--
 Description:    Get Password Parameter Value
--
 =============================================
CREATE FUNCTION [dbo].[udf_GetPasswordParameterValue] 
(
    @PasswordParameterId TINYINT
)
RETURNS TINYINT
AS
BEGIN
    DECLARE @ReturnValue TINYINT
    SELECT @ReturnValue = [ParameterValue] FROM [dbo].[PasswordParameter] WHERE [PasswordParameterId] = @PasswordParameterId
    Return @ReturnValue
END

GO

 

接下来,Insus.NET要修改有更改密码的的存储过程:

usp_Users_UpdatePassword
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
--
 Author:        Insus.NET
--
 Create date: 2008-12-26
--
 Update date: 2012-06-05 23:11:19
--
 Description:    Update User Password
--
 =============================================

ALTER PROCEDURE [dbo].[usp_Users_UpdatePassword]
(
    @ID INT,
    @OldPassword nvarchar(30),
    @Password nvarchar(30)
)
AS    

--判断用户输入的密码是否正确
IF NOT EXISTS(SELECT TOP 1 * FROM [Users] WHERE [Password] = @OldPassword AND [UsersId] = @ID)
BEGIN
    RAISERROR(N'旧密码输入不正确,无法更新!',16,1)
    RETURN
END

--下面两个变量,是从密码策略表获取最小长度与最大长度值
DECLARE @PasswordLengthMin TINYINT = [dbo].[udf_GetPasswordParameterValue](3)
DECLARE @PasswordLengthMax TINYINT = [dbo].[udf_GetPasswordParameterValue](4)

--如果大于0,说明设置了密码最小长度策略
IF @PasswordLengthMin > 0 AND LEN(@Password< @PasswordLengthMin
BEGIN
    RAISERROR(N'密码最小长度必须大于或等于%d字符。',16,1,@PasswordLengthMin)
    RETURN
END

--如果大于0,说明设置了密码最大长度策略
IF @PasswordLengthMax > 0 AND LEN(@Password> @PasswordLengthMax
BEGIN
    RAISERROR(N'密码最大长度必须小于或等于%d字符。',16,1,@PasswordLengthMax)
    RETURN
END

--更新密码
UPDATE [Users] SET [Password] = @Password WHERE [UsersId] = @ID

 

 

posted @ 2012-02-06 10:22 Insus.NET 阅读(58) 评论(0) 编辑

重构,每天对Insus.NET来说,是必须的工作,不过一直是着重C#程序。昨晚在家中修改SQL一个小问题时,无意中看到一个触发器虽然它能正确运行,但值得重构它。

这个触发器功能是当用户预定会议室成功之后,系统会发送一封预定成功的确认函邮件。下面代码是原始触发器

tri_MeetingRoomBooking_BookingSuccessNotify
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

-- =============================================
--
 Author:        Insus.NET
--
 Create date:   2011-08-07
--
 Description:   Meeting Room Booking success notify
--
 =============================================

CREATE TRIGGER [dbo].[tri_MeetingRoomBooking_BookingSuccessNotify]
ON [dbo].[MeetingRoomBooking]
FOR INSERT
AS
BEGIN
    SET NOCOUNT ON
    DECLARE @MeetingRoomBookingId INT@ContactEmail NVARCHAR(150),@CreateBy INT,@ContentPagePath NVARCHAR(1000)    
    
    --从INSERTED内存虚拟表给变量赋值    
    SELECT @MeetingRoomBookingId = [MeetingRoomBookingId],@ContactEmail = [Email],@CreateBy = [CreateBy] FROM INSERTED
    
    --设定邮件Web地址
    SET @ContentPagePath = N'http://www.yourcompany.com/MailNotify/BookingSuccess.aspx?ID=' + CONVERT(NVARCHAR(100),@MeetingRoomBookingId)
    
    --从Users表中找到预定人的邮箱
    DECLARE @CreaterEmail NVARCHAR(200)
    SELECT @CreaterEmail = [Email] FROM [dbo].[Users] WHERE [UsersId] = @CreateBy        
    
    --判断预定人与会议联系人是否为同一个人,还是帮助别人预定,并把相关的信息插入邮件发送列表中。
    IF (@ContactEmail = @CreaterEmail)    
        EXECUTE [dbo].[usp_MailingList_Insert] @Email = @ContactEmail,@Subject = N'会议室预定成功确认函',@HtmlPagePath = @ContentPagePath,@EmailParameterId = 2;
    ELSE
    BEGIN
        EXECUTE [dbo].[usp_MailingList_Insert] @Email = @ContactEmail,@Subject = N'会议室预定成功确认函',@HtmlPagePath = @ContentPagePath,@EmailParameterId = 2;
        EXECUTE [dbo].[usp_MailingList_Insert] @Email = @CreaterEmail,@Subject = N'会议室预定成功确认函',@HtmlPagePath = @ContentPagePath,@EmailParameterId = 2;
    END
END

 

重构过程以一些想法,

变量@MeetingRoomBookingId宣告的数据类型由INT改为NVARCHAR(100),这样在设置邮件Web地址时,无需对CONVERT(NVARCHAR(100),@MeetingRoomBookingId)
转换了:......aspx?ID=' + @MeetingRoomBookingId

 

从Users表中找到预定人的邮箱,是先宣告变量,由于是使用SQL2008,可以在宣告变量之后,马上赋值: 

DECLARE @CreaterEmail NVARCHAR(200= (SELECT [Email] FROM [dbo].[Users] WHERE [UsersId] = @CreateBy)

 

邮件标题,可以重构放入一个变量之中,某一天需要更改它时,只改一次即可。

@Subject NVARCHAR(50= N'会议室预定成功确认函'

 

接下是此次重构的重点是判断预定人与会议联系人是否为同一个人,还帮助别人预定,并把相关的信息插入邮件发送列表中。正常判断如原始代码写法一样,当同一个人时,直接发送给预定人就行了,如果不是同一个人,要把预定成功的邮件发送给预定人和会议联系人。

此次,Insus.NET使用了反方式判断,判断由相等,改为不相等,减少IF的层次和可以节省一代码以及提高可维护性:

IF (@ContactEmail <> @CreaterEmail)    
    EXECUTE [dbo].[usp_MailingList_Insert] @Email = @CreaterEmail,@Subject = @Subject,@HtmlPagePath = @ContentPagePath,@EmailParameterId = 2;
        
EXECUTE [dbo].[usp_MailingList_Insert] @Email = @ContactEmail,@Subject = @Subject,@HtmlPagePath = @ContentPagePath,@EmailParameterId = 2;

 

重构之后,完整代码:

tri_MeetingRoomBooking_BookingSuccessNotify
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

-- =============================================
--
 Author:        Insus.NET
--
 Create date:   2011-08-07
--
 Description:   Meeting Room Booking success notify
--
 =============================================

ALTER TRIGGER [dbo].[tri_MeetingRoomBooking_BookingSuccessNotify]
ON [dbo].[MeetingRoomBooking]
FOR INSERT
AS
BEGIN
    SET NOCOUNT ON
    DECLARE @MeetingRoomBookingId NVARCHAR(100), @ContactEmail NVARCHAR(150),@Subject NVARCHAR(50= N'会议室预定成功确认函',@CreateBy INT,@ContentPagePath NVARCHAR(1000)    
    
    --从INSERTED内存虚拟表给变量赋值    
    SELECT @MeetingRoomBookingId = [MeetingRoomBookingId],@ContactEmail = [Email],@CreateBy = [CreateBy] FROM INSERTED
    
    --设定邮件Web地址
    SET @ContentPagePath = N'http://www.yourcompany.com/MailNotify/BookingSuccess.aspx?ID=' + @MeetingRoomBookingId
    
    --从Users表中找到预定人的邮箱
    DECLARE @CreaterEmail NVARCHAR(200= (SELECT [Email] FROM [dbo].[Users] WHERE [UsersId] = @CreateBy)    
    
    --判断预定人与会议联系人是否为同一个人,还是帮助别人预定,并把相关的信息插入邮件发送列表中。    
    IF (@ContactEmail <> @CreaterEmail)    
        EXECUTE [dbo].[usp_MailingList_Insert] @Email = @CreaterEmail,@Subject = @Subject,@HtmlPagePath = @ContentPagePath,@EmailParameterId = 2;
        
    EXECUTE [dbo].[usp_MailingList_Insert] @Email = @ContactEmail,@Subject = @Subject,@HtmlPagePath = @ContentPagePath,@EmailParameterId = 2;
END

 

 

posted @ 2012-02-04 09:10 Insus.NET 阅读(137) 评论(0) 编辑

协助一个朋友做一个小网站,其中一个功能,是让用户注册成功之后,系统将随机产生一个登录密码,并自动发送至注册邮箱中,朋友的做法是为了用户使用真实邮箱。

随机产生密码,Insus.NET总结了三个,并分别写成了存储过程。

第一个,

usp_RandomPassword
CREATE PROCEDURE [dbo].[usp_RandomPassword] 
(
   @Length INT = 8
)
AS
BEGIN      
    DECLARE @RandomPassword NVARCHAR(MAX= N'',@L INT = 1
    WHILE @L <= @Length  --循环密码长度
    BEGIN
        --随机产生每一位字符,ASCII码48至122
        DECLARE @RndChar CHAR(1= CHAR(ROUND(RAND() * (122-48+1+ 48,0))
        --随机产生的字符不包括下面字符
        IF ASCII(@RndCharNOT IN(58,59,60,61,62,63,64,91,92,93,94,95,96-- : , ; , < , = , > , ? ,@ , [ , \ , ] , ^ , _ , `
        BEGIN
            SET @RandomPassword = @RandomPassword + @RndChar
            SET @L = @L + 1
        END        
    END
    SELECT @RandomPassword
END

 

第二个,

usp_RandomPassword
CREATE PROCEDURE [dbo].[usp_RandomPassword] 
(
   @Length INT = 8
)
AS
BEGIN  
    DECLARE @RandomPassword NVARCHAR(MAX= N'',@L INT = 1
    --随机密码将由下面字符串产生,数字0-9,大写字母A-Z,小写字母a-z
    DECLARE @BaseString VARCHAR(255= '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'  
    WHILE @L <= @Length --循环密码长度
    BEGIN
        --61是变量@BaseString的长度减一
        SET @RandomPassword = @RandomPassword + SUBSTRING(@BaseStringCONVERT(INT,ROUND(RAND() * 61 + 1,0)),1)
        SET @L = @L + 1
    END
    SELECT @RandomPassword
END

 

第三个,

usp_RandomPassword
CREATE PROCEDURE [dbo].[usp_RandomPassword] 
(
   @Length INT = 8
)
AS
BEGIN  
    DECLARE @RandomPassword NVARCHAR(MAX= N'' 
    DECLARE @R TINYINT,@L INT = 1      
    WHILE  @L <= @Length --循环密码长度
    BEGIN
        SET @R = ROUND(RAND() * 20)    --随机产生0,1,2整数
        IF @R = 0 --当变量为0时,将随机产生一位数字
            SET @RandomPassword = @RandomPassword + CHAR(ROUND(RAND() * 9 + 48,0)) 
        ELSE IF @R = 1 --当变量为1时,将随机产生一位大写字母
            SET @RandomPassword = @RandomPassword + CHAR(ROUND(RAND() * 25 + 65,0)) 
        ELSE IF @R = 2 --当变量为2时,将随机产生一位小写字母
            SET @RandomPassword = @RandomPassword + CHAR(ROUND(RAND() * 25 + 97,0))            
        SET @L = @L + 1
    END
    SELECT @RandomPassword
END

 

最后一个也可以重构写成:

usp_RandomPassword
CREATE PROCEDURE [dbo].[usp_RandomPassword] 
(
   @Length INT = 8
)
AS
BEGIN  
    DECLARE @RandomPassword  NVARCHAR(MAX= N'',@L INT = 1   
    WHILE @L <= @Length --循环密码长度
    BEGIN         
        DECLARE @R INT = ROUND(RAND() * 20
        SET @RandomPassword = @RandomPassword + CASE @R
        WHEN 0 THEN CHAR(ROUND(RAND() * 9 + 48,0)) 
        WHEN 1 THEN CHAR(ROUND(RAND() * 25 + 65,0)) 
        WHEN 2 THEN CHAR(ROUND(RAND() * 25 + 97,0)) END                            
        SET @L = @L + 1        
    END
    SELECT @RandomPassword
END

 

Also reference:

MS SQL随机数  http://www.cnblogs.com/insus/archive/2012/01/27/2330058.html

不重复的随机数 http://www.cnblogs.com/insus/archive/2012/01/27/2330104.html

 

posted @ 2012-01-31 14:50 Insus.NET 阅读(214) 评论(1) 编辑
摘要: 开发的软件中是允许用户可以更自己的密码,现在客户有这样一个要求,是当用户更新密码时,要限制用户不能重新使用最近三次的历史密码。实现客户的要求,唯有在数据库,创建一个密码更新Log表,然后再为Member表写一个触发器,每当用户更新密码时,去检索这个Log表,看看这次更新的密码是否存在Log表中,如果存在,提示用户,返之继续更新动作,然后把更新的信息插入Log表中,最后是删除Log记录,只保留此用户最近三次记录。相关代码,可以参考:MemberPasswordChangeLog CREATETABLEMemberPasswordChangeLog(Log_IdINTIDENTITY(1,1)PR阅读全文
posted @ 2012-01-30 15:00 Insus.NET 阅读(182) 评论(5) 编辑
摘要: “大哥,看了你这篇博文http://www.cnblogs.com/insus/archive/2012/01/27/2330058.html,我怎样才能产生10个且每个有8位不相同的随机数字?”刚才有位网友在SKYPE问及如上问题。好的,Insus.NET也正想写一个存储过程来应用上面这篇的SQL语句,你可以参考如下的存储过程,如果还问题请继续讨论。usp_RandomNumberCREATEPROCEDURE[dbo].[usp_RandomNumber](@LenINT=1,--随机数位数@RowsINT=1--随机笔数)ASBEGINDECLARE@TASTABLE([RandomNu阅读全文
posted @ 2012-01-27 14:33 Insus.NET 阅读(172) 评论(0) 编辑
摘要: MS SQL有一个函数CHAR()是将int(0-255) ASCII代码转换为字符。那我们可以使用下面MS SQL语句,可以随机生成小写、大写字母,特殊字符和数字。大写字母:CHAR(ROUND(RAND() * 25 + 65,0))小写字母:CHAR(ROUND(RAND() * 25 + 97,0))特殊字符:CHAR(ROUND(RAND()*13+33,0))数字:CHAR(ROUND(RAND()*9+48,0))阅读全文
posted @ 2012-01-27 11:10 Insus.NET 阅读(130) 评论(0) 编辑