Commit 4a595b2d by jhrabal

um

parent 450bb536
...@@ -95,3 +95,14 @@ CREATE TABLE APP_USER_ROLE ( ...@@ -95,3 +95,14 @@ CREATE TABLE APP_USER_ROLE (
); );
CREATE INDEX APP_USER_ROLE_IDX ON APP_USER_ROLE(USER_ID, ROLE_ID); CREATE INDEX APP_USER_ROLE_IDX ON APP_USER_ROLE(USER_ID, ROLE_ID);
CREATE TABLE RESET_PASSWORD_TOKEN (
ID INT8 NOT NULL,
LOGIN VARCHAR(250) NOT NULL,
TOKEN VARCHAR(250) NOT NULL,
USED BOOLEAN DEFAULT FALSE,
CREATED TIMESTAMP,
CONSTRAINT PK_RESET_PASSWORD_TOKEN PRIMARY KEY(ID)
);
CREATE INDEX RESET_PASSWORD_TOKEN_LOGIN_IDX ON RESET_PASSWORD_TOKEN(LOGIN);
package com.jh.common.security; package com.jh.common.security;
import java.util.List;
import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
...@@ -28,9 +27,8 @@ public interface AuthService { ...@@ -28,9 +27,8 @@ public interface AuthService {
* Register. * Register.
* *
* @param signup the signup * @param signup the signup
* @return the list
*/ */
List<AuthError> register(Signup signup); void register(String login, String password) throws AuthenticationException;
/** /**
...@@ -41,15 +39,14 @@ public interface AuthService { ...@@ -41,15 +39,14 @@ public interface AuthService {
* *
* @param login * @param login
*/ */
void generateResetToken(String login); String generateResetToken(String login);
/** /**
* TODO * TODO
* @param resetPassword * @param resetPassword
* * @throws AuthenticationException TODO
* @return
*/ */
List<AuthError> resetPassword(ResetPassword resetPassword); void resetPassword(String login, String token, String newPassword) throws AuthenticationException;
} }
package com.jh.common.security;
import org.springframework.security.core.GrantedAuthority;
public class GrantedRole implements GrantedAuthority {
private static final long serialVersionUID = 1L;
private String role;
public GrantedRole(String role) {
super();
this.role = role;
}
@Override
public String getAuthority() {
return role;
}
}
...@@ -2,20 +2,17 @@ package com.jh.common.security; ...@@ -2,20 +2,17 @@ package com.jh.common.security;
import java.io.IOException; import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import com.jh.common.security.repository.AppUserRepository; import com.jh.common.security.repository.AppUserRepository;
import com.jh.common.security.service.AppUserAuthService; import com.jh.common.security.service.AppUserAuthService;
...@@ -32,18 +29,21 @@ public class JhSecurityConfig extends WebSecurityConfigurerAdapter { ...@@ -32,18 +29,21 @@ public class JhSecurityConfig extends WebSecurityConfigurerAdapter {
*/ */
@Override @Override
protected void configure(HttpSecurity http) throws Exception { protected void configure(HttpSecurity http) throws Exception {
http HttpSecurity cfg = http
.authorizeRequests() .authorizeRequests()
.antMatchers("/auth/**").permitAll() .antMatchers("/auth/**").permitAll()
.anyRequest().authenticated() .anyRequest().authenticated()
.and() .and()
.logout() .logout()
.clearAuthentication(true) .clearAuthentication(true)
.permitAll(); .permitAll()
.and();
cfg.httpBasic();
http.csrf().disable(); http.csrf().disable();
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint()); http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint());
http.headers().frameOptions().sameOrigin(); http.headers().frameOptions().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
} }
...@@ -56,7 +56,7 @@ public class JhSecurityConfig extends WebSecurityConfigurerAdapter { ...@@ -56,7 +56,7 @@ public class JhSecurityConfig extends WebSecurityConfigurerAdapter {
*/ */
@Override @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception { protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.eraseCredentials(true); auth.authenticationProvider(authenticationProvider());
} }
...@@ -76,20 +76,17 @@ public class JhSecurityConfig extends WebSecurityConfigurerAdapter { ...@@ -76,20 +76,17 @@ public class JhSecurityConfig extends WebSecurityConfigurerAdapter {
}; };
} }
@Bean
protected AuthenticationSuccessHandler authenticationSuccessHandler() { public AuthenticationProvider authenticationProvider() {
return new SimpleUrlAuthenticationSuccessHandler() { return new AuthServiceAuthenticationProvider();
@Override
public void onAuthenticationSuccess( final HttpServletRequest request, final HttpServletResponse response, final Authentication authentication ) throws ServletException, IOException {
this.clearAuthenticationAttributes( request );
}
};
} }
@Bean @Bean
public AuthService authService() { public AuthService authService() {
return new AppUserAuthService(); AppUserAuthService appUserAuthService = new AppUserAuthService();
appUserAuthService.setAppUserRepository(appUserRepository());
return appUserAuthService;
} }
@Bean @Bean
......
package com.jh.common.security;
/**
* The Class ResetPassword.
*/
public class ResetPassword {
/** The username. */
private String username;
/** The password. */
private String password;
private String token;
/**
* Gets the username.
*
* @return the username
*/
public String getUsername() {
return username;
}
/**
* Sets the username.
*
* @param username the new username
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Gets the password.
*
* @return the password
*/
public String getPassword() {
return password;
}
/**
* Sets the password.
*
* @param password the new password
*/
public void setPassword(String password) {
this.password = password;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
package com.jh.common.security;
import java.util.Locale;
/**
* The Class Signup.
*/
public class Signup {
/** The username. */
private String username;
/** The password. */
private String password;
/** The locale. */
private Locale locale = Locale.ENGLISH;
/**
* Gets the username.
*
* @return the username
*/
public String getUsername() {
return username;
}
/**
* Sets the username.
*
* @param username the new username
*/
public void setUsername(String username) {
this.username = username;
}
/**
* Gets the password.
*
* @return the password
*/
public String getPassword() {
return password;
}
/**
* Sets the password.
*
* @param password the new password
*/
public void setPassword(String password) {
this.password = password;
}
/**
* Gets the locale.
*
* @return the locale
*/
public Locale getLocale() {
return locale;
}
/**
* Sets the locale.
*
* @param locale the new locale
*/
public void setLocale(Locale locale) {
this.locale = locale;
}
}
...@@ -8,7 +8,6 @@ import java.util.ArrayList; ...@@ -8,7 +8,6 @@ import java.util.ArrayList;
import java.util.Base64; import java.util.Base64;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
...@@ -30,10 +29,10 @@ import org.springframework.web.bind.annotation.ResponseStatus; ...@@ -30,10 +29,10 @@ import org.springframework.web.bind.annotation.ResponseStatus;
import com.jh.common.security.AuthError; import com.jh.common.security.AuthError;
import com.jh.common.security.AuthService; import com.jh.common.security.AuthService;
import com.jh.common.security.PasswordUtils; import com.jh.common.security.PasswordUtils;
import com.jh.common.security.ResetPassword;
import com.jh.common.security.Signup;
import com.jh.common.utils.Utils; import com.jh.common.utils.Utils;
import com.jh.common.web.error.BadRequestException;
import com.jh.common.web.error.ErrorMessage; import com.jh.common.web.error.ErrorMessage;
import com.jh.common.web.error.NotFoundException;
import com.jh.common.web.error.RestApiException; import com.jh.common.web.error.RestApiException;
/** /**
...@@ -101,21 +100,19 @@ public class AuthApiController { ...@@ -101,21 +100,19 @@ public class AuthApiController {
* @return the response entity * @return the response entity
*/ */
@RequestMapping(path = "/auth/signup", method = RequestMethod.POST) @RequestMapping(path = "/auth/signup", method = RequestMethod.POST)
public ResponseEntity<List<AuthError>> signup(@RequestBody Signup signup, Locale locale) { public @ResponseBody LoginResponse signup(@RequestBody Signup signup) {
if (!signupEnabled) { if (!signupEnabled) {
return ResponseEntity.notFound().build(); throw new NotFoundException();
} }
//validate //validate
if (signup == null) { if (signup == null) {
return new ResponseEntity<>(Collections.singletonList(new AuthError(null, "BadRequest")), HttpStatus.BAD_REQUEST); throw new BadRequestException();
} }
signup.setLocale(locale);
List<AuthError> errors = new ArrayList<>(); List<AuthError> errors = new ArrayList<>();
//TODO validate email //TODO validate email
if (!StringUtils.hasText(signup.getUsername())) { if (!StringUtils.hasText(signup.getLogin())) {
errors.add(new AuthError("username", "BadUsername")); errors.add(new AuthError("username", "BadUsername"));
} }
...@@ -123,26 +120,22 @@ public class AuthApiController { ...@@ -123,26 +120,22 @@ public class AuthApiController {
errors.add(new AuthError("password", "BadPassword")); errors.add(new AuthError("password", "BadPassword"));
} }
if (!errors.isEmpty()) {
// throw new BadRequestException(errors);
throw new BadRequestException();
}
try { try {
List<AuthError> errs = authService.register(signup); authService.register(signup.getLogin(), signup.getPassword());
if (errs == null || errs.isEmpty()) { // Authentication auth = authService.authenticate(signup.getLogin(), signup.getPassword());
Authentication auth = authService.authenticate(signup.getUsername(), signup.getPassword()); // SecurityContextHolder.getContext().setAuthentication(auth);
SecurityContextHolder.getContext().setAuthentication(auth);
} else {
errors.addAll(errs);
}
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
errors.add(new AuthError(null, e.getMessage())); errors.add(new AuthError(null, e.getMessage()));
} }
//everything was OK - log user in return new LoginResponse("Authentication", "Basic " + Base64.getEncoder().encodeToString((signup.getLogin() + ":" + signup.getPassword()).getBytes()));
if (errors.isEmpty()) {
//return no errors
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<>(errors, HttpStatus.BAD_REQUEST);
} }
...@@ -151,7 +144,8 @@ public class AuthApiController { ...@@ -151,7 +144,8 @@ public class AuthApiController {
if (!resetEnabled) { if (!resetEnabled) {
return ResponseEntity.notFound().build(); return ResponseEntity.notFound().build();
} }
authService.generateResetToken(request.getUsername()); Utils.sleep(250);
authService.generateResetToken(request.getLogin());
return ResponseEntity.accepted().build(); return ResponseEntity.accepted().build();
} }
...@@ -161,6 +155,7 @@ public class AuthApiController { ...@@ -161,6 +155,7 @@ public class AuthApiController {
if (!resetEnabled) { if (!resetEnabled) {
return ResponseEntity.notFound().build(); return ResponseEntity.notFound().build();
} }
Utils.sleep(250);
String token = resetPassword.getToken(); String token = resetPassword.getToken();
if (!StringUtils.hasText(token)) { if (!StringUtils.hasText(token)) {
return new ResponseEntity<>(Collections.singletonList(new AuthError(null, "BadRequest")), HttpStatus.BAD_REQUEST); return new ResponseEntity<>(Collections.singletonList(new AuthError(null, "BadRequest")), HttpStatus.BAD_REQUEST);
...@@ -169,13 +164,13 @@ public class AuthApiController { ...@@ -169,13 +164,13 @@ public class AuthApiController {
List<AuthError> errors = new ArrayList<>(); List<AuthError> errors = new ArrayList<>();
try { try {
List<AuthError> errs = authService.resetPassword(resetPassword); authService.resetPassword(resetPassword.getLogin(), resetPassword.getToken(), resetPassword.getPassword());
if (errs == null || errs.isEmpty()) { // if (errs == null || errs.isEmpty()) {
Authentication auth = authService.authenticate(resetPassword.getUsername(), resetPassword.getPassword()); // Authentication auth = authService.authenticate(resetPassword.getLogin(), resetPassword.getPassword());
SecurityContextHolder.getContext().setAuthentication(auth); // SecurityContextHolder.getContext().setAuthentication(auth);
} else { // } else {
errors.addAll(errs); // errors.addAll(errs);
} // }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
errors.add(new AuthError(null, e.getMessage())); errors.add(new AuthError(null, e.getMessage()));
......
package com.jh.common.security.api;
public class ResetPassword {
private String login;
private String token;
private String password;
public ResetPassword() {
super();
}
public ResetPassword(String login, String token, String password) {
super();
this.login = login;
this.token = token;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getToken() {
return token;
}
public void setToken(String password) {
this.token = password;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package com.jh.common.security.api;
public class Signup {
private String login;
private String password;
public Signup() {
super();
}
public Signup(String login, String password) {
super();
this.login = login;
this.password = password;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
package com.jh.common.security.model;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import com.jh.common.jpa.AbstractIdEntity;
@Entity
@Table(name = "RESET_PASSWORD_TOKEN")
public class ResetPasswordToken extends AbstractIdEntity {
private static final long serialVersionUID = 1L;
@Column(name = "LOGIN")
private String login;
@Column(name = "CREATED")
private Date created;
@Column(name = "TOKEN")
private String token;
@Column(name = "USED")
private Boolean used;
public ResetPasswordToken() {
super();
}
public ResetPasswordToken(String login, Date created, String token) {
super();
this.login = login;
this.created = created;
this.token = token;
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public Boolean getUsed() {
return used;
}
public void setUsed(Boolean used) {
this.used = used;
}
}
...@@ -5,12 +5,14 @@ import javax.persistence.Query; ...@@ -5,12 +5,14 @@ import javax.persistence.Query;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import com.jh.common.jpa.AbstractHibernateRepository; import com.jh.common.jpa.AbstractHibernateRepository;
import com.jh.common.security.PasswordHash;
import com.jh.common.security.PasswordUtils;
import com.jh.common.security.model.AppUser; import com.jh.common.security.model.AppUser;
public class AppUserRepository extends AbstractHibernateRepository { public class AppUserRepository extends AbstractHibernateRepository {
public AppUser findByUsername(String username) { public AppUser findByLogin(String username) {
if (!StringUtils.hasText(username)) { if (!StringUtils.hasText(username)) {
return null; return null;
} }
...@@ -19,4 +21,18 @@ public class AppUserRepository extends AbstractHibernateRepository { ...@@ -19,4 +21,18 @@ public class AppUserRepository extends AbstractHibernateRepository {
return singleResult(q); return singleResult(q);
} }
public AppUser registerUser(String username, String password) {
AppUser user = new AppUser();
user.setEmail(username);
PasswordHash hash = PasswordUtils.hashPassword(password);
user.setPassword(hash.getHash());
user.setPasswordSalt(hash.getSalt());
entityManager.persist(user);
return user;
}
} }
package com.jh.common.security.service; package com.jh.common.security.service;
import java.util.List; import java.util.HashSet;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import com.jh.common.security.AuthError;
import com.jh.common.security.AuthService; import com.jh.common.security.AuthService;
import com.jh.common.security.GrantedRole;
import com.jh.common.security.PasswordUtils; import com.jh.common.security.PasswordUtils;
import com.jh.common.security.ResetPassword;
import com.jh.common.security.Signup;
import com.jh.common.security.model.AppUser; import com.jh.common.security.model.AppUser;
import com.jh.common.security.repository.AppUserRepository; import com.jh.common.security.repository.AppUserRepository;
...@@ -25,35 +26,48 @@ public class AppUserAuthService implements AuthService { ...@@ -25,35 +26,48 @@ public class AppUserAuthService implements AuthService {
@Override @Override
@Transactional @Transactional
public Authentication authenticate(String username, String password) throws BadCredentialsException { public Authentication authenticate(String login, String password) throws BadCredentialsException {
AppUser user = appUserRepository.findByUsername(username); AppUser user = appUserRepository.findByLogin(login);
if (user == null) { if (user == null) {
throw new BadCredentialsException("User not found"); throw new BadCredentialsException("User not found");
} }
if (!PasswordUtils.checkPassword(password, user.getPassword(), user.getPasswordSalt())) { if (!PasswordUtils.checkPassword(password, user.getPassword(), user.getPasswordSalt())) {
throw new BadCredentialsException("Bad password"); throw new BadCredentialsException("Bad password");
} }
return new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword());
Set<GrantedRole> roles = new HashSet<>();
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword(), roles);
return auth;
} }
@Override @Override
public List<AuthError> register(Signup signup) { @Transactional
return null; public void register(String login, String password) throws AuthenticationException {
AppUser user = appUserRepository.findByLogin(login);
if (user != null) {
throw new BadCredentialsException("User already exists");
}
if (!StringUtils.hasText(login) || !StringUtils.hasText(password)) {
throw new BadCredentialsException("Bad username or password");
}
appUserRepository.registerUser(login, password);
} }
@Override @Override
public void generateResetToken(String login) { @Transactional
public String generateResetToken(String login) {
return "TOKEN";
} }
@Override @Override
public List<AuthError> resetPassword(ResetPassword resetPassword) { @Transactional
return null; public void resetPassword(String login, String token, String newPassword) throws AuthenticationException {
} }
@Autowired(required = false) @Autowired(required = false)
public void setAppUserRepository(AppUserRepository appUserRepository) { public void setAppUserRepository(AppUserRepository appUserRepository) {
this.appUserRepository = appUserRepository; this.appUserRepository = appUserRepository;
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment