001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.security; 020 021import java.io.IOException; 022import java.util.Set; 023 024import lucee.commons.digest.MD5; 025import lucee.commons.io.IOUtil; 026import lucee.commons.io.res.Resource; 027import lucee.runtime.coder.Base64Coder; 028import lucee.runtime.exp.ApplicationException; 029import lucee.runtime.exp.PageException; 030import lucee.runtime.op.Caster; 031import lucee.runtime.type.Array; 032import lucee.runtime.type.util.ListUtil; 033 034/** 035 * User Password Information 036 */ 037public final class CredentialImpl implements Credential { 038 String username; 039 String password; 040 String[] roles; 041 private Resource rolesDir; 042 private static final char ONE=(char)1; 043 044 /** 045 * credential constructor 046 * @param username 047 */ 048 public CredentialImpl(String username,Resource rolesDir) { 049 this(username,null,new String[0],rolesDir); 050 } 051 052 /** 053 * credential constructor 054 * @param username 055 * @param password 056 */ 057 public CredentialImpl(String username,String password,Resource rolesDir) { 058 this(username,password,new String[0],rolesDir); 059 } 060 061 /** 062 * credential constructor 063 * @param username 064 * @param password 065 * @param roles 066 * @throws PageException 067 */ 068 public CredentialImpl(String username,String password, String roles,Resource rolesDir) throws PageException { 069 this(username,password,toRole(roles),rolesDir); 070 } 071 072 /** 073 * credential constructor 074 * @param username 075 * @param password 076 * @param roles 077 * @throws PageException 078 */ 079 public CredentialImpl(String username,String password, Array roles,Resource rolesDir) throws PageException { 080 this(username,password,toRole(roles),rolesDir); 081 } 082 083 /** 084 * credential constructor 085 * @param username 086 * @param password 087 * @param roles 088 */ 089 public CredentialImpl(String username,String password,String[] roles,Resource rolesDir) { 090 this.username=username; 091 this.password=password; 092 this.roles=roles; 093 this.rolesDir=rolesDir; 094 } 095 096 @Override 097 public String getPassword() { 098 return password; 099 } 100 @Override 101 public String[] getRoles() { 102 return roles; 103 } 104 @Override 105 public String getUsername() { 106 return username; 107 } 108 109 /** 110 * convert a Object to a String Array of Roles 111 * @param oRoles 112 * @return roles 113 * @throws PageException 114 */ 115 public static String[] toRole(Object oRoles) throws PageException { 116 if(oRoles instanceof String) { 117 oRoles=ListUtil.listToArrayRemoveEmpty(oRoles.toString(),","); 118 } 119 120 if(oRoles instanceof Array) { 121 Array arrRoles = (Array) oRoles; 122 String[] roles=new String[arrRoles.size()]; 123 for(int i=0;i<roles.length;i++) { 124 roles[i]=Caster.toString(arrRoles.get(i+1,"")); 125 } 126 return roles; 127 } 128 throw new ApplicationException("invalid roles definition for tag loginuser"); 129 } 130 131 public String serialize() { 132 return serialize(null); 133 } 134 135 public String serialize(Set<Object> done) { 136 return "createObject('java','lucee.runtime.security.Credential').init('"+username+"','"+password+"','"+ListUtil.arrayToList(roles,",")+"')"; 137 } 138 139 140 @Override 141 public String encode() throws PageException{ 142 String raw=ListUtil.arrayToList(roles,","); 143 if(raw.length()>100){ 144 try { 145 if(!rolesDir.exists())rolesDir.mkdirs(); 146 String md5 = MD5.getDigestAsString(raw); 147 IOUtil.write(rolesDir.getRealResource(md5), raw, "utf-8", false); 148 return Caster.toB64(username+ONE+password+ONE+"md5:"+md5,"UTF-8"); 149 } 150 catch (IOException e) {} 151 } 152 try { 153 return Caster.toB64(username+ONE+password+ONE+raw,"UTF-8"); 154 } catch (Exception e) { 155 throw Caster.toPageException(e); 156 } 157 } 158 159 /** 160 * decode the Credential form a Base64 String value 161 * @param encoded 162 * @return Credential from decoded string 163 * @throws PageException 164 */ 165 public static Credential decode(Object encoded,Resource rolesDir) throws PageException { 166 String dec; 167 try { 168 dec=Base64Coder.decodeToString(Caster.toString(encoded),"UTF-8"); 169 } catch (Exception e) { 170 throw Caster.toPageException(e); 171 } 172 173 Array arr=ListUtil.listToArray(dec,""+ONE); 174 int len=arr.size(); 175 if(len==3) { 176 String str=Caster.toString(arr.get(3,"")); 177 if(str.startsWith("md5:")){ 178 if(!rolesDir.exists())rolesDir.mkdirs(); 179 str=str.substring(4); 180 Resource md5 = rolesDir.getRealResource(str); 181 try { 182 str=IOUtil.toString(md5, "utf-8"); 183 } catch (IOException e) { 184 str=""; 185 } 186 } 187 188 return new CredentialImpl(Caster.toString(arr.get(1,"")),Caster.toString(arr.get(2,"")),str,rolesDir); 189 } 190 if(len==2) return new CredentialImpl(Caster.toString(arr.get(1,"")),Caster.toString(arr.get(2,"")),rolesDir); 191 if(len==1) return new CredentialImpl(Caster.toString(arr.get(1,"")),rolesDir); 192 193 return null; 194 } 195 196 @Override 197 public String toString() { 198 return "username:"+username+";password:"+password+";roles:"+roles; 199 } 200 201}