📄 mod_htaccess.erl
字号:
%----------------------------------------------------------------------getAllowDenyOrder(AccessData)-> case ets:lookup(AccessData,order) of [{order,{deny,allow}}]-> {deny,ets:lookup(AccessData,deny), allow,ets:lookup(AccessData,allow)}; _DefaultOrder-> {allow,ets:lookup(AccessData,allow), deny,ets:lookup(AccessData,deny)} end. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% The methods that validates the user %%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%----------------------------------------------------------------------%Control if there is anyu autheticating data in threquest header%if so it controls it against the users in the list Allowed Users%----------------------------------------------------------------------authenticateUser(Info,AccessData,AllowedUsers)-> case getAuthenticatingDataFromHeader(Info) of {user,User,PassWord}-> authenticateUser(Info,AccessData,AllowedUsers, {user,User,PassWord}); {error,nouser}-> challenge; {error, _BadData}-> challenge end.%----------------------------------------------------------------------%Returns the Autheticating data in the http-request%----------------------------------------------------------------------getAuthenticatingDataFromHeader(Info)-> PrsedHeader=Info#mod.parsed_header, case httpd_util:key1search(PrsedHeader,"authorization" ) of undefined-> {error,nouser}; [$B,$a,$s,$i,$c,$\ |EncodedString] = Credentials -> case (catch http_base_64:decode(EncodedString)) of {'EXIT',{function_clause, _}} -> {error, Credentials}; UnCodedString -> case httpd_util:split(UnCodedString,":",2) of {ok,[User,PassWord]}-> {user,User,PassWord}; {error,Error}-> {error,Error} end end; BadCredentials -> {error,BadCredentials} end.%----------------------------------------------------------------------%Returns a list of all members of the allowed groups%----------------------------------------------------------------------getGroupMembers(Groups,AllowedGroups)-> Allowed=lists:foldl(fun({group,Name,Members},AllowedMembers)-> case lists:member(Name,AllowedGroups) of true-> AllowedMembers++Members; false -> AllowedMembers end end,[],Groups), {ok,Allowed}. authenticateUser(Info,AccessData,{{users,[]},{groups,Groups}},User)-> authenticateUser(Info,AccessData,{groups,Groups},User);authenticateUser(Info,AccessData,{{users,Users},{groups,[]}},User)-> authenticateUser(Info,AccessData,{users,Users},User);authenticateUser(Info,AccessData,{{users,Users},{groups,Groups}},User)-> AllowUser=authenticateUser(Info,AccessData,{users,Users},User), AllowGroup=authenticateUser(Info,AccessData,{groups,Groups},User), case {AllowGroup,AllowUser} of {_,allow}-> allow; {allow,_}-> allow; {challenge,_}-> challenge; {_,challenge}-> challenge; {_deny,_deny}-> deny end; %----------------------------------------------------------------------%Controls that the user is a member in one of the allowed group%----------------------------------------------------------------------authenticateUser(Info,AccessData,{groups,AllowedGroups},{user,User,PassWord})-> case getUsers(AccessData,group_file) of {group_data,Groups}-> {ok, Members } = getGroupMembers(Groups,AllowedGroups), authenticateUser(Info,AccessData,{users,Members}, {user,User,PassWord}); {error, _BadData}-> deny end;%----------------------------------------------------------------------%Control that the user is one of the allowed users and that the passwd is ok%----------------------------------------------------------------------authenticateUser(_Info,AccessData,{users,AllowedUsers},{user,User,PassWord})-> case lists:member(User,AllowedUsers) of true-> %Get the usernames and passwords from the file case getUsers(AccessData,user_file) of {error, _BadData}-> deny; {user_data,Users}-> %Users is a list of the users in %the userfile [{user,User,Passwd}] checkPassWord(Users,{user,User,PassWord}) end; false -> challenge end.%----------------------------------------------------------------------%Control that the user User={user,"UserName","PassWd"} is%member of the list of Users%----------------------------------------------------------------------checkPassWord(Users,User)-> case lists:member(User,Users) of true-> allow; false-> challenge end.%----------------------------------------------------------------------%Get the users in the specified file%UserOrGroup is an atom that specify if its a group file or a user file%i.e. group_file or user_file%----------------------------------------------------------------------getUsers({file,FileName},UserOrGroup)-> case file:open(FileName,[read]) of {ok,AccessFileHandle} -> getUsers({stream,AccessFileHandle},[],UserOrGroup); {error,Reason} -> {error,{Reason,FileName}} end;%----------------------------------------------------------------------%The method that starts the lokkong for user files%----------------------------------------------------------------------getUsers(AccessData,UserOrGroup)-> case ets:lookup(AccessData,UserOrGroup) of [{UserOrGroup,File}]-> getUsers({file,File},UserOrGroup); _ -> {error,noUsers} end. %----------------------------------------------------------------------%Reads data from the filehandle File to the list FileData and when its%reach the end it returns the list in a tuple {user_file|group_file,FileData}%----------------------------------------------------------------------getUsers({stream,File},FileData,UserOrGroup)-> case io:get_line(File,[]) of eof when UserOrGroup==user_file-> {user_data,FileData}; eof when UserOrGroup ==group_file-> {group_data,FileData}; Line -> getUsers({stream,File}, formatUser(Line,FileData,UserOrGroup),UserOrGroup) end. %----------------------------------------------------------------------%If the line is a comment remove it%----------------------------------------------------------------------formatUser([$#|_UserDataComment],FileData,_UserOrgroup)-> FileData;%----------------------------------------------------------------------%The user name in the file is Username:Passwd\n %Remove the newline sign and split the user name in %UserName and Password%----------------------------------------------------------------------formatUser(UserData,FileData,UserOrGroup)-> case string:tokens(UserData," \r\n")of [User| _Whitespace] when UserOrGroup==user_file-> case string:tokens(User,":") of [Name,PassWord]-> [{user,Name,PassWord}|FileData]; _Error-> FileData end; GroupData when UserOrGroup==group_file -> parseGroupData(GroupData,FileData); _Error -> FileData end.%----------------------------------------------------------------------%if everything is right GroupData is on the form% ["groupName:", "Member1", "Member2", "Member2"%----------------------------------------------------------------------parseGroupData([GroupName|GroupData],FileData)-> [{group,formatGroupName(GroupName),GroupData}|FileData].%----------------------------------------------------------------------%the line in the file is GroupName: Member1 Member2 .....MemberN%Remove the : from the group name%---------------------------------------------------------------------- formatGroupName(GroupName)-> string:strip(GroupName,right,$:).%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%% Functions that parses the accessfiles %%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%----------------------------------------------------------------------%Control that the asset is a real file and not a request for an virtual%asset%----------------------------------------------------------------------isErlScriptOrNotAccessibleFile(Path, _Info)-> case file:read_file_info(Path) of {ok,_fileInfo}-> false; {error,_Reason} -> true end.%----------------------------------------------------------------------%Path=PathToTheRequestedFile=String%Innfo=record#mod%----------------------------------------------------------------------getHtAccessData(Path,Info)-> HtAccessFileNames=getHtAccessFileNames(Info), case getData(Path,Info,HtAccessFileNames) of {ok,public}-> {ok,public}; {accessData,AccessData}-> {accessData,AccessData}; {error,Reason} -> {error,Reason} end.%----------------------------------------------------------------------%returns the names of the accessfiles%----------------------------------------------------------------------getHtAccessFileNames(Info)-> case httpd_util:lookup(Info#mod.config_db,access_files) of undefined-> [".htaccess"]; Files-> Files end.%----------------------------------------------------------------------%HtAccessFileNames=["accessfileName1",..."AccessFileName2"]%----------------------------------------------------------------------getData(Path,Info,HtAccessFileNames)-> case regexp:split(Path,"/") of {error,Error}-> {error,Error}; {ok,SplittedPath}-> getData2(HtAccessFileNames,SplittedPath,Info) end.%----------------------------------------------------------------------%Add to together the data in the Splittedpath up to the path %that is the alias or the document root%Since we do not need to control after any accessfiles before here%----------------------------------------------------------------------getData2(HtAccessFileNames,SplittedPath,Info)-> case getRootPath(SplittedPath,Info) of {error,Path}-> {error,Path}; {ok,StartPath,RestOfSplittedPath} -> getData2(HtAccessFileNames,StartPath,RestOfSplittedPath,Info) end.%----------------------------------------------------------------------%HtAccessFilenames is a list the names the accesssfiles can have%Path is the shortest match agains all alias and documentroot%rest of splitted path is a list of the parts of the path%Info is the mod recod from the server %----------------------------------------------------------------------getData2(HtAccessFileNames, StartPath, RestOfSplittedPath, _Info)-> case getHtAccessFiles(HtAccessFileNames,StartPath,RestOfSplittedPath) of []-> %No accessfile qiut its a public directory {ok,public}; Files -> loadAccessFilesData(Files) end.%----------------------------------------------------------------------%Loads the data in the accessFiles specifiied by % AccessFiles=["/hoem/public/html/accefile",% "/home/public/html/priv/accessfile"]%----------------------------------------------------------------------loadAccessFilesData(AccessFiles)-> loadAccessFilesData(AccessFiles,ets:new(accessData,[])).%----------------------------------------------------------------------%Returns the found data%----------------------------------------------------------------------contextToValues(AccessData)-> case ets:lookup(AccessData,context) of [{context,Values}]-> ets:delete(AccessData,context), insertContext(AccessData,Values), {accessData,AccessData}; _Error-> {error,errorInAccessFile} end.insertContext(_AccessData, [])-> ok;insertContext(AccessData,[{allow,From}|Values])-> insertDenyAllowContext(AccessData,{allow,From}), insertContext(AccessData,Values); insertContext(AccessData,[{deny,From}|Values])-> insertDenyAllowContext(AccessData,{deny,From}), insertContext(AccessData,Values);insertContext(AccessData,[{require,{GrpOrUsr,Members}}|Values])-> case ets:lookup(AccessData,require) of []when GrpOrUsr==users-> ets:insert(AccessData,{require,{{users,Members},{groups,[]}}}); [{require,{{users,Users},{groups,Groups}}}]when GrpOrUsr==users -> ets:insert(AccessData,{require,{{users,Users++Members}, {groups,Groups}}}); []when GrpOrUsr==groups-> ets:insert(AccessData,{require,{{users,[]},{groups,Members}}});
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -