I have a problem with password hashing. I want to appply sha-256 with salt and 1024 iterations to authenticate my users using Spring Security. But somehow, my password in database dont match those from user input.
Here is my code:
security-context.xml
<beans:bean
id="passwordEncoder"
class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" >
<beans:constructor-arg value="256" />
<beans:property
name="iterations"
value="1024" />
</beans:bean>
<beans:bean class="org.springframework.security.authentication.dao.ReflectionSaltSource" id="saltSource">
<beans:property name="userPropertyToUse" value="id"/>
</beans:bean>
<authentication-manager>
<authentication-provider user-service-ref="userLoginDetails" >
<password-encoder ref="passwordEncoder" >
<salt-source ref="saltSource"/>
</password-encoder>
</authentication-provider>
</authentication-manager>
userLoginDetails
#Transactional(readOnly = true)
public class UserLoginDetails implements UserDetailsService {
private EregDaoFactory daoFactory;
#Autowired
public void setDaoFactory(EregDaoFactory daoFactory) {
this.daoFactory = daoFactory;
}
/**
* Retrieves a user record containing the user's credentials and access.
*/
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException,
DataAccessException {
Logger logger = Logger.getLogger(getClass());
logger.setLevel(Level.ALL);
int userId = Integer.parseInt(username);
UzytkownikDao dao = daoFactory.getUzytkownikDao();
LoggedUser user = null;
Uzytkownik dbUser = null;
try {
dbUser = (Uzytkownik) dao.findById(Integer.parseInt(username));
List<SimpleGrantedAuthority> grants = new ArrayList<SimpleGrantedAuthority>();
Collection<Object> userNames = new ArrayList<Object>();
if (dbUser.getRola() == 'U') {
grants.add(new SimpleGrantedAuthority("ROLE_STUDENT"));
userNames = daoFactory.getUczenDao().getNameAndLastName(userId);
} else if (dbUser.getRola() == 'N') {
grants.add(new SimpleGrantedAuthority("ROLE_TEACHER"));
userNames = daoFactory.getNauczycielDao().getNameAndLastName(userId);
} else if (dbUser.getRola() == 'O') {
grants.add(new SimpleGrantedAuthority("ROLE_PARENT"));
userNames = daoFactory.getOpiekunDao().getNameAndLastName(userId);
}
grants.add(new SimpleGrantedAuthority("ROLE_USER"));
Object[] names = userNames.toArray();
user =
new LoggedUser(username, dbUser.getHaslo(), true, true, true, true, grants,
(String) names[0], (String) names[1], dbUser.getRola());
} catch (Exception e) {
logger.error(e.getLocalizedMessage());
throw new UsernameNotFoundException("Error in retrieving user");
}
return user;
}
}
LoggedUser
package ereg.security.userdetails;
public class LoggedUser extends User {
private static final long serialVersionUID = 1L;
private final String id;
private final String imie;
private final String nazwisko;
private final char rola;
private Date lastSuccessfulLogin;
private String lastKnowIpAddress;
public LoggedUser(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked,
Collection<? extends GrantedAuthority> authorities, String name, String lastName, char rola) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked,
authorities);
this.imie = name;
this.nazwisko = lastName;
this.rola = rola;
this.id = username;
}
public String getId() {
return id;
}
public String getImie() {
return imie;
}
public String getNazwisko() {
return nazwisko;
}
public char getRola() {
return rola;
}
public Date getLastSuccessfulLogin() {
return lastSuccessfulLogin;
}
public String getFormattedDate() {
if (lastSuccessfulLogin != null) {
return new SimpleDateFormat("dd/MM/yyyy, HH:mm:ss").format(lastSuccessfulLogin);
} else
return null;
}
public String getLastKnowIpAddress() {
return lastKnowIpAddress;
}
public void setLastSuccessfulLogin(Date lastSuccessfulLogin) {
this.lastSuccessfulLogin = lastSuccessfulLogin;
}
public void setLastKnowIpAddress(String lastKnowIpAddress) {
this.lastKnowIpAddress = lastKnowIpAddress;
}
}
And here is the program that hashes passwords:
EncryptAllUsersPasswords
private void encryptPasswords() throws Exception {
OneWayEncryptor encryptor = OneWayEncryptor.getInstance();
appContext =
new FileSystemXmlApplicationContext(
"C:/EclipseWorkSpace/myereg/WebContent/WEB-INF/applicationContext.xml");
ds = (DataSource) appContext.getBean("dataSource");
JdbcTemplate jdbc = new JdbcTemplate(ds);
BigDecimal userId = null;
String password = "";
String encrypted = "";
Map<?, ?> row = new HashMap<Object, Object>();
for (Iterator<?> it = jdbc.queryForList("SELECT id, haslo FROM UZYTKOWNIK").iterator(); it.hasNext();) {
row = (Map<?, ?>) it.next();
userId = (BigDecimal) row.get("ID");
password = (String) row.get("HASLO");
encrypted = encryptor.encrypt(password, userId.toString());
System.out.println(userId.toString());
jdbc.execute("UPDATE UZYTKOWNIK SET haslo = '" + encrypted + "' WHERE id = " + userId);
}
}
public static void main(String[] args) {
EncryptAllUserPasswords encrypt = new EncryptAllUserPasswords();
try {
encrypt.encryptPasswords();
} catch (Exception e) {
e.printStackTrace();
}
}
OneWayEncryptor
public final class OneWayEncryptor {
private static final OneWayEncryptor INSTANCE = new OneWayEncryptor();
private static final int ITERATIONS = 1024;
private static final String ALGORITHM = "SHA-256";
private OneWayEncryptor() {
}
public static OneWayEncryptor getInstance() {
return INSTANCE;
}
public String encrypt(String plaintext, String salt) throws NoSuchAlgorithmException,
UnsupportedEncodingException {
MessageDigest messageDigest = MessageDigest.getInstance(ALGORITHM);
messageDigest.reset();
messageDigest.update(salt.getBytes());
byte[] btPass = messageDigest.digest(plaintext.getBytes("UTF-8"));
for (int i = 0; i < ITERATIONS; i++) {
messageDigest.reset();
btPass = messageDigest.digest(btPass);
}
String encodedPassword = byteToBase64(btPass);
return encodedPassword;
}
private String byteToBase64(byte[] bt) throws UnsupportedEncodingException {
return new String(Base64.encodeBase64(bt));
}
}
I believe that problem lies in the last one... Please help
actually, this worked:
public String encrypt(String plaintext, String salt) throws NoSuchAlgorithmException,
UnsupportedEncodingException {
String pass = plaintext + "{" + salt + "}";
MessageDigest messageDigest = MessageDigest.getInstance(ALGORITHM);
messageDigest.reset();
byte[] btPass = messageDigest.digest(pass.getBytes("UTF-8"));
for (int i = 0; i < ITERATIONS - 1; i++) {
messageDigest.reset();
btPass = messageDigest.digest(btPass);
}
String hashedPass = new BigInteger(1, btPass).toString(16);
if (hashedPass.length() < 32) {
hashedPass = "0" + hashedPass;
}
return hashedPass;
}
can someone tell my why? I mean why when i tried using update(salt) method it didint and when i switch to concate string it did. and i dont mind part with "{salt}", cause that only allows me to generate exactly the same hash as spring does. the thing is that before it generated wrong hash even with given salt. I checked it with sha256 generators. Can someone tell me why it started working after string concatating?
Related
I'm looking for a way to validate apple's login token.
The validation must be done on backend side so i'm sure that i can add a new account safely.
Onother issue is that i need to convert the key https://appleid.apple.com/auth/keys in xml format to Public Key pem format.
I have found a possible solution that I will post below.
The code is implemented in Java
public static void main(String...args) throws Exception {
String jwtAppleToken = ""; //copy here the token from apple
//copied from https://appleid.apple.com/auth/keys
final String base64UrlEncodedModulus = "lxrwmuYSAsTfn-lUu4goZSXBD9ackM9OJuwUVQHmbZo6GW4Fu_auUdN5zI7Y1dEDfgt7m7QXWbHuMD01HLnD4eRtY-RNwCWdjNfEaY_esUPY3OVMrNDI15Ns13xspWS3q-13kdGv9jHI28P87RvMpjz_JCpQ5IM44oSyRnYtVJO-320SB8E2Bw92pmrenbp67KRUzTEVfGU4-obP5RZ09OxvCr1io4KJvEOjDJuuoClF66AT72WymtoMdwzUmhINjR0XSqK6H0MdWsjw7ysyd_JhmqX5CAaT9Pgi0J8lU_pcl215oANqjy7Ob-VMhug9eGyxAWVfu_1u6QJKePlE-w";
final String base64UrlEncodedExp = "AQAB";
String publicKey = getPemPublicKeyFromBase64UrlEncodedXMLRSAKey(base64UrlEncodedModulus, base64UrlEncodedExp);
System.out.println(verify(jwtAppleToken, publicKey));
System.out.println("-----BEGIN PUBLIC KEY-----");
System.out.println(publicKey);
System.out.println("-----END PUBLIC KEY-----");
}
The same solution with Jose4 lib,
This HttpsJwksVerificationKeyResolver will pick the public key based on key id from the list. so we don't have to deal with it.
import org.jose4j.jwk.HttpsJwks;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
import org.jose4j.keys.resolvers.HttpsJwksVerificationKeyResolver;
HttpsJwks httpsJkws = new HttpsJwks("https://appleid.apple.com/auth/keys");
HttpsJwksVerificationKeyResolver httpsJwksKeyResolver = new HttpsJwksVerificationKeyResolver(httpsJkws);
JwtConsumer jwtConsumer = new JwtConsumerBuilder()
.setVerificationKeyResolver(httpsJwksKeyResolver)
.setExpectedIssuer("https://appleid.apple.com")
.setExpectedAudience(<clientId>)
.build();
JwtClaims jwtClaims = jwtConsumer.processToClaims(<idToken>);
processToClaims will throw appropriate exceptions, just catch and act accordingly.
Hope this keeps simple and makes more readable for other developers.
This is a possible solution for the validation of the apple login token.
The implementation uses the Apple public key published on --> https://appleid.apple.com/auth/keys
The keys are converted in PEM format from XML format (https://appleid.apple.com/auth/keys) and than the token is validated.
Some of the code can be used to convert modulus and exponent in string format to RSA Public key in PEM Format
import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.RsaVerifier;
public class VerifyAppleToken {
public static void main(String...args) throws Exception {
String jwtAppleToken = ""; //copy here the token from apple
System.out.println("THE TOKEN IS VERIFIED FOR ONE OF APPLE KEYS:"+verify(jwtAppleToken));
//copied from https://appleid.apple.com/auth/keys
final String base64UrlEncodedModulus = "lxrwmuYSAsTfn-lUu4goZSXBD9ackM9OJuwUVQHmbZo6GW4Fu_auUdN5zI7Y1dEDfgt7m7QXWbHuMD01HLnD4eRtY-RNwCWdjNfEaY_esUPY3OVMrNDI15Ns13xspWS3q-13kdGv9jHI28P87RvMpjz_JCpQ5IM44oSyRnYtVJO-320SB8E2Bw92pmrenbp67KRUzTEVfGU4-obP5RZ09OxvCr1io4KJvEOjDJuuoClF66AT72WymtoMdwzUmhINjR0XSqK6H0MdWsjw7ysyd_JhmqX5CAaT9Pgi0J8lU_pcl215oANqjy7Ob-VMhug9eGyxAWVfu_1u6QJKePlE-w";
final String base64UrlEncodedExp = "AQAB";
String publicKey = getPemPublicKeyFromBase64UrlEncodedXMLRSAKey(base64UrlEncodedModulus, base64UrlEncodedExp);
System.out.println(verify(jwtAppleToken, publicKey));
//copied from and converted to base64 from base64UrlEncoded https://appleid.apple.com/auth/keys on
// 07/02/2020
final String base64EncodedModulus = "lxrwmuYSAsTfn+lUu4goZSXBD9ackM9OJuwUVQHmbZo6GW4Fu/auUdN5zI7Y1dEDfgt7m7QXWbHuMD01HLnD4eRtY+RNwCWdjNfEaY/esUPY3OVMrNDI15Ns13xspWS3q+13kdGv9jHI28P87RvMpjz/JCpQ5IM44oSyRnYtVJO+320SB8E2Bw92pmrenbp67KRUzTEVfGU4+obP5RZ09OxvCr1io4KJvEOjDJuuoClF66AT72WymtoMdwzUmhINjR0XSqK6H0MdWsjw7ysyd/JhmqX5CAaT9Pgi0J8lU/pcl215oANqjy7Ob+VMhug9eGyxAWVfu/1u6QJKePlE+w==";
final String base64EncodedExp = "AQAB";
System.out.println("-----BEGIN PUBLIC KEY-----");
System.out.println(getPemPublicKeyFromBase64XMLRSAKey(base64EncodedModulus, base64EncodedExp));
System.out.println("-----END PUBLIC KEY-----");
}
private static boolean verify(String jwtAppleToken) throws NoSuchAlgorithmException, InvalidKeySpecException {
AppleKeysRetrieverService retriver = new AppleKeysRetrieverService();
AppleKeysResponse res = retriver.sendRetriveRequest("https://appleid.apple.com/auth/keys");
List<AppleKeyDTO> appleKeys = res.getKeys();
for (AppleKeyDTO appleKeyDTO : appleKeys) {
final String base64UrlEncodedModulus = appleKeyDTO.getN();
final String base64UrlEncodedExp = appleKeyDTO.getE();
String publicKey1 = getPemPublicKeyFromBase64UrlEncodedXMLRSAKey(base64UrlEncodedModulus, base64UrlEncodedExp);
if(verify(jwtAppleToken, publicKey1)) {
return true;
}
}
return false;
}
public static boolean verify(String jwtToken, String publicKey) {
try {
JwtHelper.decodeAndVerify(jwtToken, new RsaVerifier(getRSAPublicKey(publicKey)));
} catch (Exception e) {
return false;
}
return true;
}
private static RSAPublicKey getRSAPublicKey(String publicKey) throws NoSuchAlgorithmException, InvalidKeySpecException {
KeyFactory keyFactory = java.security.KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(java.util.Base64.getDecoder().decode(publicKey));
return (RSAPublicKey) keyFactory.generatePublic(keySpec);
}
private static String getPemPublicKeyFromBase64UrlEncodedXMLRSAKey(String urlBase64Modulus, String urlBase64Exp) throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] e = Base64.getUrlDecoder().decode(urlBase64Exp);
byte[] n = Base64.getUrlDecoder().decode(urlBase64Modulus);
BigInteger exponent = new BigInteger(1, e);
BigInteger modulus = new BigInteger(1, n);
return getPemPublicKey(modulus, exponent);
}
private static String getPemPublicKeyFromBase64XMLRSAKey(String base64Modulus, String base64Exp) throws NoSuchAlgorithmException, InvalidKeySpecException {
byte[] e = Base64.getDecoder().decode(base64Exp);
byte[] n = Base64.getDecoder().decode(base64Modulus);
BigInteger exponent = new BigInteger(1, e);
BigInteger modulus = (new BigInteger(1, n));
return getPemPublicKey(modulus, exponent);
}
private static String getPemPublicKey(BigInteger modulus, BigInteger exponent) throws NoSuchAlgorithmException, InvalidKeySpecException {
RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(modulus, exponent);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey myPublicKey = keyFactory.generatePublic(publicKeySpec);
byte[] park = Base64.getEncoder().encode(myPublicKey.getEncoded());
return new String(park);
}
}
RETRIVE APPLE KEYS:
public class AppleKeysRetrieverService {
public AppleKeysResponse sendRetriveRequest(String retriveAppleKeysUrl) {
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters()
.add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8));
String appleKeysResponse = restTemplate
.getForObject(retriveAppleKeysUrl, String.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
AppleKeysResponse res = null;
try {
res = objectMapper.readValue(appleKeysResponse, AppleKeysResponse.class);
return res;
}catch(Exception e) {
return null;
}
}
}
public class AppleKeyDTO {
public String kty;
public String kid;
public String sig;
public String alg;
public String n;
public String e;
public String getKty() {
return kty;
}
public void setKty(String kty) {
this.kty = kty;
}
public String getKid() {
return kid;
}
public void setKid(String kid) {
this.kid = kid;
}
public String getSig() {
return sig;
}
public void setSig(String sig) {
this.sig = sig;
}
public String getAlg() {
return alg;
}
public void setAlg(String alg) {
this.alg = alg;
}
public String getN() {
return n;
}
public void setN(String n) {
this.n = n;
}
public String getE() {
return e;
}
public void setE(String e) {
this.e = e;
}
}
public class AppleKeysResponse {
private List<AppleKeyDTO> keys;
public List<AppleKeyDTO> getKeys() {
return keys;
}
public void setKeys(List<AppleKeyDTO> keys) {
this.keys = keys;
}
}
I am developing an ADF web application with Oracle EBS as the backend to call the procedure(Jdeveloper 12 c).
I have invoked a method calling EBS procedure (return type is list) and the result is stored in arraylist. the list is used to create Data control.
What my problem is i have set values to the data control but when i added that dc to view it shows nothing. But on debugging it shows all the values are set in the array list.
Bean class calling EBS procedure in ApplicationModule
BindingContainer bindings = getBindings();
OperationBinding operationBinding = (OperationBinding) bindings.getOperationBinding("getIexpenseLogin");
List<EmployeePojo> result = (List<EmployeePojo>) operationBinding.execute();
System.out.println("Result= " + result);
employeeDC.getEmployeeLogin(result); // Here the list is passed to the Employee DC class to create data controll.
ApplicationModule Containing Custom Procedure
public List getIexpenseLogin(String username,String password){
CallableStatement cs=null;
List<EmployeePojo> empList=new ArrayList<>();
try{
cs=getDBTransaction().createCallableStatement("begin xx_oie_mob_login.oie_mob_login(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?); end;",0);
cs.setString(1,username);
cs.setString(2, password);
cs.registerOutParameter(3, Types.NUMERIC);
cs.registerOutParameter(4, Types.VARCHAR);
cs.registerOutParameter(5, Types.VARCHAR);
cs.registerOutParameter(6, Types.NUMERIC);
cs.registerOutParameter(7, Types.VARCHAR);
cs.registerOutParameter(8, Types.NUMERIC);
cs.registerOutParameter(9, Types.VARCHAR);
cs.registerOutParameter(10, Types.NUMERIC);
cs.registerOutParameter(11, Types.VARCHAR);
cs.registerOutParameter(12, Types.NUMERIC);
cs.registerOutParameter(13, Types.BLOB);
cs.registerOutParameter(14, Types.VARCHAR);
cs.registerOutParameter(15, Types.VARCHAR);
cs.executeUpdate();
if(cs!=null)
{
EmployeePojo ePojo=new EmployeePojo();
ePojo.setEmployeeId(cs.getString(3));
ePojo.setEmployeeName(cs.getString(4));
ePojo.setEmployeeNumber(cs.getString(5));
ePojo.setManagerId(cs.getString(6));
ePojo.setManagerName(cs.getString(7));
ePojo.setJobId(cs.getString(8));
ePojo.setJobName(cs.getString(9));
ePojo.setOrgId(cs.getString(10));
ePojo.setOrgName(cs.getString(11));
ePojo.setImgId(cs.getString(12));
ePojo.setImage(cs.getBlob(13));
empList.add(ePojo);
}
return empList;
}catch(SQLException e){
throw new JboException(e);
}
}
EmployeeDC class used to create Data controll
public class EmployeeDC {
public EmployeeDC() {
super();
}
BindingContainer bindings = null;
private List<EmployeePojo> employee_data_controll=null;
private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
public void setEmployee_data_controll(List<EmployeePojo> employee_data_controll) {
List<EmployeePojo> oldEmployee_data_controll = this.employee_data_controll;
this.employee_data_controll = employee_data_controll;
propertyChangeSupport.firePropertyChange("employee_data_controll", oldEmployee_data_controll,
employee_data_controll);
}
public List<EmployeePojo> getEmployee_data_controll() {
return employee_data_controll;
}
public void setPropertyChangeSupport(PropertyChangeSupport propertyChangeSupport) {
PropertyChangeSupport oldPropertyChangeSupport = this.propertyChangeSupport;
this.propertyChangeSupport = propertyChangeSupport;
propertyChangeSupport.firePropertyChange("propertyChangeSupport", oldPropertyChangeSupport,
propertyChangeSupport);
}
public PropertyChangeSupport getPropertyChangeSupport() {
return propertyChangeSupport;
}
public void getEmployeeLogin(List<EmployeePojo> result) {
setEmployee_data_controll(result);
getEmployee_data_controll();
System.out.println("DataControl=>"+getEmployee_data_controll().get(0));
}
public void addPropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.removePropertyChangeListener(l);
}
}
EmployeePojo Class
public class EmployeePojo {
private String employeeId;
private String employeeName;
private String employeeNumber;
private String managerId;
private String managerName;
private String jobId;
private String jobName;
private String orgId;
private String orgName;
private String imgId;
private Blob image;
private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
public void setPropertyChangeSupport(PropertyChangeSupport propertyChangeSupport) {
this.propertyChangeSupport = propertyChangeSupport;
}
public PropertyChangeSupport getPropertyChangeSupport() {
return propertyChangeSupport;
}
public void setEmployeeId(String employeeId) {
String oldEmployeeId = this.employeeId;
this.employeeId = employeeId;
propertyChangeSupport.firePropertyChange("employeeId", oldEmployeeId, employeeId);
}
public String getEmployeeId() {
return employeeId;
}
public void setEmployeeName(String employeeName) {
String oldEmployeeName = this.employeeName;
this.employeeName = employeeName;
propertyChangeSupport.firePropertyChange("employeeName", oldEmployeeName, employeeName);
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeNumber(String employeeNumber) {
String oldEmployeeNumber = this.employeeNumber;
this.employeeNumber = employeeNumber;
propertyChangeSupport.firePropertyChange("employeeNumber", oldEmployeeNumber, employeeNumber);
}
public String getEmployeeNumber() {
return employeeNumber;
}
public void setManagerId(String managerId) {
String oldManagerId = this.managerId;
this.managerId = managerId;
propertyChangeSupport.firePropertyChange("managerId", oldManagerId, managerId);
}
public String getManagerId() {
return managerId;
}
public void setManagerName(String managerName) {
String oldManagerName = this.managerName;
this.managerName = managerName;
propertyChangeSupport.firePropertyChange("managerName", oldManagerName, managerName);
}
public String getManagerName() {
return managerName;
}
public void setJobId(String jobId) {
String oldJobId = this.jobId;
this.jobId = jobId;
propertyChangeSupport.firePropertyChange("jobId", oldJobId, jobId);
}
public String getJobId() {
return jobId;
}
public void setJobName(String jobName) {
String oldJobName = this.jobName;
this.jobName = jobName;
propertyChangeSupport.firePropertyChange("jobName", oldJobName, jobName);
}
public String getJobName() {
return jobName;
}
public void setOrgId(String orgId) {
String oldOrgId = this.orgId;
this.orgId = orgId;
propertyChangeSupport.firePropertyChange("orgId", oldOrgId, orgId);
}
public String getOrgId() {
return orgId;
}
public void setOrgName(String orgName) {
String oldOrgName = this.orgName;
this.orgName = orgName;
propertyChangeSupport.firePropertyChange("orgName", oldOrgName, orgName);
}
public String getOrgName() {
return orgName;
}
public void setImgId(String imgId) {
String oldImgId = this.imgId;
this.imgId = imgId;
propertyChangeSupport.firePropertyChange("imgId", oldImgId, imgId);
}
public String getImgId() {
return imgId;
}
public void setImage(Blob image) {
Blob oldImage = this.image;
this.image = image;
propertyChangeSupport.firePropertyChange("image", oldImage, image);
}
public Blob getImage() {
return image;
}
public void addPropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.addPropertyChangeListener(l);
}
public void removePropertyChangeListener(PropertyChangeListener l) {
propertyChangeSupport.removePropertyChangeListener(l);
}
}
I have three interceptors in my application and i just want to prioritize them, actually i want to auto login my application from another application via query params.
This interceptor is validating the user session if user doesn't have valid session then it will redirect user to login page and it is working fine.
public class ValidateSessionInterceptor extends HandlerInterceptorAdapter {
private Logger log = Logger.getLogger(getClass());
#Value("${http.port}")
private int httpPort;
#Value("${https.port}")
private int httpsPort;
#Value("${use.ssl}")
private boolean useSsl;
//before the actual handler will be executed
public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {
HttpSession session = request.getSession();
if(session.getAttribute("user")==null){
String forwardTo = (String) request.getAttribute("org.springframework.web.servlet.HandlerMapping.pathWithinHandlerMapping");
String params = "";
if(request.getQueryString()!=null){
params = "?" + request.getQueryString();
}
String url = getApplicationUrl(request,useSsl)+forwardTo+params;
log.info("redirect url: " + request.getContextPath()+"/login/index.mars?forwardTo="+URLEncoder.encode(url, "UTF-8"));
response.sendRedirect(request.getContextPath()+"/login/index.mars?forwardTo="+URLEncoder.encode(url, "UTF-8"));
return false;
}else{
Map<String,String> owners = new LinkedHashMap<String,String>();
owners.put("NA", "NA");
owners.put("AK", "AK");
request.setAttribute("ownerList", owners);
}
return true;
}
private String getApplicationUrl(HttpServletRequest request,boolean useSsl){
if(useSsl){
return "https://"+request.getServerName()+":"+httpsPort+request.getContextPath();
}else{
return "http://"+request.getServerName()+":"+httpPort+request.getContextPath();
}
}
}
This is being called by another application and passing autoUsr and autoPwd parameters to auto logged in application.
public class AutoLoginInterceptor extends HandlerInterceptorAdapter{
private final Logger log = Logger.getLogger(getClass());
#Autowired
public UserService userService;
#Autowired
public WebService webService;
public boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws IOException, UserException {
HttpSession session = request.getSession();
if(session.getAttribute("user")==null){
String forwardTo = request.getParameter("forwardTo");
if(forwardTo!=null && !forwardTo.equals("")){
User user = checkLoginCrendential(forwardTo);
log.info("user-> " + user);
this.webService.buildWebService(request);
if(userService.login(request, user)){
session.setAttribute("user", user);
return true;
}
}
}
return true;
}
public User checkLoginCrendential(String url){
String decURL;
User user = new User();
try
{
decURL = URLDecoder.decode(url,"utf-8");
String params[] = (decURL.split("\\?")[1]).split("&");
String loginParams[] = {"autoUsr","autoPwd"};
for(String lgnParam : loginParams){
for(int i = 0 ; i < params.length ; i++){
String param[] = params[i].split("=");
if(lgnParam.equals(param[0])){
if(param.length > 1){
if(lgnParam.equals("autoUsr")){
user.setUsername(param[1]);
}else if(lgnParam.equals("autoPwd")){
user.setPassword(param[1]);
}
}else{
if(lgnParam.equals("autoUsr")){
user.setUsername("");
}else if(lgnParam.equals("autoPwd")){
user.setPassword("");
}
}
}
}
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return user;
}
}
You can use tag to order interceptors in XXX-servlet.xml. For example :
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="ValidateSessionInterceptor" />
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="AutoLoginInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
interceptors will be called by order
*After I add a session attribute using
WebUtils.setSessionAttribute(request, VBWebConstants.SESSION_ORDER_BEAN,sellerDetails);
#RequestMapping(value="/minasidor/step1",method=RequestMethod.GET)
public ModelAndView step1(HttpServletRequest request,HttpSession session){
if(logger.isTraceEnabled())logger.trace("VbSellerController ::: step1 ::: start");
if(logger.isDebugEnabled())logger.debug("[Order Step1] [Start]");
ModelAndView mav=new ModelAndView("vz-new/mina-sidor/v-orderstep1");
LoginBean user = (LoginBean) WebUtils.getSessionAttribute(request, VBWebConstants.SESSION_USER);
mav.addObject("submenu",3);
if(!checkOrderLifeCycle()){
mav.addObject("orderNotAllowed", false);
return mav;
}
try{
String orderValue = "";
orderValue = InMemoryCache.getCaProperty(PropertyEnum.MIN_ORDER_VALUE.getDatabasekey());
int minimumOrderValue = CawebUtil.isInt(orderValue);
CpSellerDetails sellerDetails=vbOrderService.getStep1Data(user.getGrp_seller_id(),user.getCatalogue_id());
if(sellerDetails != null){
mav.addObject("productlist",sellerDetails.getSellerList());
mav.addObject("totalValue",sellerDetails.getTotalOrderValue());
mav.addObject("allowedfororder",sellerDetails.getTotalOrderValue() > minimumOrderValue);
// mav addobject add discount details Discount Object ArrayList
WebUtils.setSessionAttribute(request, VBWebConstants.SESSION_ORDER_STEP_COMPLETED,"step1");
WebUtils.setSessionAttribute(request, VBWebConstants.SESSION_ORDER_BEAN,sellerDetails);
}else{
mav.addObject("allowedfororder",false);
WebUtils.setSessionAttribute(request, VBWebConstants.SESSION_ORDER_STEP_COMPLETED,null);
}
}catch(DataNotFoundException e){
logger.trace("Exception in retrieving data for step1",e);
if(logger.isDebugEnabled())logger.debug("[Order Step1 Exception]",e);
}
if(logger.isTraceEnabled())logger.trace("VbSellerController ::: step1 ::: end");
if(logger.isDebugEnabled())logger.debug("[Order Step1] [end]");
return mav;
}
Within this step1 method the VBWebConstants.SESSION_ORDER_BEAN session attribute is getting removed instantly after the step1() method finishes executing where as the other session attributes remains the same.When i debug the below Http Listener class
public class MyHttpSessionListener implements HttpSessionListener,HttpSessionAttributeListener {
public static final Logger logger = Logger.getLogger(MyHttpSessionListener.class);
public void sessionCreated(HttpSessionEvent se) {
//String ipAddr = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest().getRemoteAddr();
HttpSession session = se.getSession();
if(logger.isDebugEnabled()){
StringBuilder sbuilder = new StringBuilder();
sbuilder.append("\n").append("----------- Session Created -------------- ");
Enumeration<String> sessionAttrs = session.getAttributeNames();
while (sessionAttrs.hasMoreElements()) {
String name = sessionAttrs.nextElement();
sbuilder.append("\n").append(" session created ").append(name);
}
sbuilder.append("\n").append(" session created time "+ CawebUtil.getTimeStampInString(new Timestamp(session.getCreationTime())));
sbuilder.append("\n").append("---------------------------------------------------- ").append("\n");
logger.debug(sbuilder.toString());
}
}
public void sessionDestroyed(HttpSessionEvent se) {
HttpSession session = se.getSession();
if(logger.isDebugEnabled()){
try{
String ipAddr = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest().getRemoteAddr();
logger.debug(" session destroyed " +ipAddr);
}catch (Exception e) {
}
}
}
public void attributeAdded(HttpSessionBindingEvent se) {
String ipAddr = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest().getRemoteAddr();
HttpSession session = se.getSession();
if(logger.isDebugEnabled()){
StringBuilder sbuilder = new StringBuilder();
sbuilder.append("\n").append("----------- Attribute added -------------- from ").append(ipAddr);
sbuilder.append("\n").append(" session max inactive time "+ session.getMaxInactiveInterval());
sbuilder.append("\n").append(" session id "+ session.getId());
sbuilder.append("\n").append(" session attribute added "+ se.getName()).append(" = ").append(se.getValue());
sbuilder.append("\n").append(" session created time "+ CawebUtil.getTimeStampInString(new Timestamp(session.getCreationTime())));
}
}
public void attributeRemoved(HttpSessionBindingEvent se) {
if(logger.isDebugEnabled() ){
StringBuilder sbuilder = new StringBuilder();
sbuilder.append("\n").append("----------- Attribute removed -------------- from ");//.append(ipAddr);
sbuilder.append("\n").append(" session attribute removed "+ se.getName()).append(" = ").append(se.getValue());
}
}
public void attributeReplaced(HttpSessionBindingEvent se) {
if(logger.isDebugEnabled()){
StringBuilder sbuilder = new StringBuilder();
sbuilder.append("\n").append("----------- Attribute replaced -------------- from ");//.append(ipAddr);
sbuilder.append("\n").append(" session attribute "+ se.getName()).append(" = ").append(se.getValue());
}
}
}
I found that the session attribute is getting removed.Checked through the entire code I couldn't find what's the reason...???
Here is the CPSellerDetails class which i try to add to the session there are other 2 session attributes among which one is a string object and other is a bean.could it the size of the class that is the cause for session attribute being removed abnormally
public class CpSellerDetails implements Serializable{
/**
*
*/
private static final long serialVersionUID = -4627284179051380310L;
private List<SellerProduct> sellerList ;
private float totalOrderValue ;
private VbCpInfoBean cpinfoBean;
private Integer orderno;
private float invoiceAmount;
private Date orderedDate;
private ArrayList<DiscountVO> discounts;
private Address billingInfo;
public VbCpInfoBean getCpInfoBean() {
return cpinfoBean;
}
public void setCpInfoBean(VbCpInfoBean infoBean) {
this.cpinfoBean = infoBean;
}
public List<SellerProduct> getSellerList() {
return sellerList;
}
public void setSellerList(List<SellerProduct> sellerList) {
this.sellerList = sellerList;
}
public float getTotalOrderValue() {
return totalOrderValue;
}
public void setTotalOrderValue(float totalOrderValue) {
this.totalOrderValue = totalOrderValue;
}
public float getInvoiceAmount() {
return invoiceAmount;
}
public void setInvoiceAmount(float invoiceAmount) {
this.invoiceAmount = invoiceAmount;
}
public Integer getOrderno() {
return orderno;
}
public void setOrderno(Integer orderno) {
this.orderno = orderno;
}
public Date getOrderedDate() {
return orderedDate;
}
public void setOrderedDate(Date orderedDate) {
this.orderedDate = orderedDate;
}
public ArrayList<DiscountVO> getDiscounts() {
return discounts;
}
public void setDiscounts(ArrayList<DiscountVO> discounts) {
this.discounts = discounts;
}
public Address getBillingInfo() {
return billingInfo;
}
public void setBillingInfo(Address billingInfo) {
this.billingInfo = billingInfo;
}
}*
Here is the config from shiro.ini
shiro.loginUrl = /login.jsp
######### URL CONFIG ################### [urls] /login.jsp = anon /public/login/** = anon /public/app/** = authc
Stripes...
#UrlBinding("/public/app/")
public class CalculatorActionBean implements ActionBean {
.....
}
#UrlBinding("/public/login/")
public class UserAuthenticateBean implements ActionBean {
private static final transient Logger log = LoggerFactory.getLogger(UserAuthenticateBean.class);
private ActionBeanContext context;
private String username;
private String password;
private String message;
public ActionBeanContext getContext() {
return context;
}
public void setContext(ActionBeanContext context) {
this.context = context;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
#DefaultHandler
#DontValidate
public Resolution defaultHander() {
return new ForwardResolution("/login.jsp");
}
public Resolution login() {
Subject currentUser = SecurityUtils.getSubject();
log.info("CU=" + currentUser.toString());
if (!currentUser.isAuthenticated()) {
TenantAuthenticationToken token = new TenantAuthenticationToken(username, password, "jdbcRealm");
//UsernamePasswordToken token = new UsernamePasswordToken("akumar", "ash");
token.setRememberMe(true);
try {
currentUser.login(token);
} catch (UnknownAccountException uae) {
log.info("There is no user with username of " + token.getPrincipal());
} catch (IncorrectCredentialsException ice) {
log.info("Password for account " + token.getPrincipal() + " was incorrect!");
} catch (LockedAccountException lae) {
log.info("The account for username " + token.getPrincipal() + " is locked. "
+ "Please contact your administrator to unlock it.");
} // ... catch more exceptions here (maybe custom ones specific to your application?
catch (AuthenticationException ae) {
//unexpected condition? error?
ae.printStackTrace();
}
}
if (currentUser.isAuthenticated()) {
message = "Success";
} else {
message = "Fail";
}
System.out.println(message);
message += getUsername() + getPassword();
return new ForwardResolution("/logged_in.jsp");
}
}
logged_in.jsp
app
Now if I remove the line
/public/app/** = authc
from shiro.ini, I can access /public/app for a logged in user and guest
If I keep the line, then noone can access the page and it goes back to login.jsp
Driving me nuts!
help!!
Change your urls config to have 'authc' filter the actual login url:
[main]
...
authc.loginUrl = /login.jsp
[urls]
/login.jsp = authc
/public/login/** = anon
/public/app/** = authc
The authc filter is smart enough to know if a request is not authenticated to still let it go through to the underlying page so a user can log in.