Authentication with Spring Security + Spring data + MongoDB - java

I want to use Spring security with MongoDB (using Spring data) and retrieve the users from my own database for spring security. However, I can not do that since my userservice type does not seem to be supported.
This is my UserService class:
public class UserService {
private ApplicationContext applicationContext;
private MongoOperations mongoOperations;
public UserService() {
applicationContext = new AnnotationConfigApplicationContext(MongoConfig.class);
mongoOperations = (MongoOperations) applicationContext.getBean("mongoTemplate");
}
public User find(String username) {
return mongoOperations.findOne(Query.query(Criteria.where("username").is(username)), User.class);
}
}
And my SecurityConfig class:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserService userService;
#Autowired
public void configAuthBuilder(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(userService); //THIS DOES NOT WORK
builder.inMemoryAuthentication().withUser("username").password("password").roles("USER");
}
}
The line I commented says:
The inferred type UserService is not a valid substitute for the bounded parameter <T extends UserDetailsService>.
How can I fix it so I can retrieve the users from my own database?

Service Layer
You have to create a separate service implementing org.springframework.security.core.userdetails.UserDetailsService and inject it inside the AuthenticationManagerBuilder.
#Component
public class SecUserDetailsService implements UserDetailsService{
#Autowired
private UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
/*Here add user data layer fetching from the MongoDB.
I have used userRepository*/
User user = userRepository.findByUsername(username);
if(user == null){
throw new UsernameNotFoundException(username);
}else{
UserDetails details = new SecUserDetails(user);
return details;
}
}
}
Model
UserDetails Should be also implemented. This is the POJO which will keep the user authenticated details by the Spring. You may include your Entity data object wrapped inside it, as I have done.
public class SecUserDetails implements UserDetails {
private User user;
public SecUserDetails(User user) {
this.user = user;
}
......
......
......
}
Security Config
Autowire the service that we created before and set it inside the AuthenticationManagerBuilder
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
SecUserDetailsService userDetailsService ;
#Autowired
public void configAuthBuilder(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(userDetailsService);
}
}

Create your own authentication provider providing a class that extends the UserDetailservice.
Ensure content scanning is enable in your spring context xml file.
<authentication-provider user-service-ref="userModelService">
<password-encoder hash="sha" />
</authentication-provider>
#Service
public class UserModelService implements UserDetailsService
{
#Autowired
private UserModelRepositoryImpl repository;
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
{
UserModel user = repository.findByUsername(username);
if( user == null )
throw new UsernameNotFoundException( "Name not found!" );
List<SimpleGrantedAuthority> authorities = Arrays.asList(new SimpleGrantedAuthority( user.getRole()));
return new User(user.getUsername(), user.getSHA1Password(), authorities );
}
public void saveUserDetails(UserModel userModel)
{
repository.save(userModel);
}
}
This class will enable spring query mongo for the username and password required for authentication. Next create the user model class.
public class UserModel
{
private String id;
#Indexed(unique=true)
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
Create the user implementation class that extends the DAO.
#Service
public class UserModelService implements UserDetailsService
{
#Autowired
private UserModelRepositoryImpl repository;
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
{
UserModel user = repository.findByUsername(username);
if( user == null )
throw new UsernameNotFoundException( "Oops!" );
List<SimpleGrantedAuthority> authorities = Arrays.asList(new SimpleGrantedAuthority( user.getRole()));
return new User(user.getUsername(), user.getSHA1Password(), authorities );
}
Finally configure mongo and you're done.

Related

Spring security | Why do I get bad credentials when they are valid?

So I am working on a Spring boot project and security is one of the things I want to have in this project.
I am having this problem where my code always goes to the BadCredentialsException, but I thought my credentials are correct.
My AuthenticationController:
#RestController
#CrossOrigin
public class JwtAuthenticationController {
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private JwtTokenUtil jwtTokenUtil;
#Autowired
private JwtUserDetailsService userDetailsService;
#RequestMapping(value = "/authenticate", method = RequestMethod.POST)
public ResponseEntity<?> createAuthenticationToken(#RequestBody JwtRequest authenticationRequest) throws Exception {
authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());
final UserDetails userDetails = userDetailsService
.loadUserByUsername(authenticationRequest.getUsername());
final String token = jwtTokenUtil.generateToken(userDetails);
return ResponseEntity.ok(new JwtResponse(token));
}
private void authenticate(String username, String password) throws Exception {
try {
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
} catch (DisabledException e) {
throw new Exception("USER_DISABLED", e);
} catch (BadCredentialsException e) {
throw new Exception("INVALID_CREDENTIALS", e);
}
}
#RequestMapping(value = "/register", method = RequestMethod.POST)
public ResponseEntity<?> saveUser(#RequestBody UserDTO user) throws Exception {
return ResponseEntity.ok(userDetailsService.save(user));
}
}
My UserDetailsService:
#Service
public class JwtUserDetailsService implements UserDetailsService {
#Autowired
private UserDao userDao;
#Autowired
private PasswordEncoder bcryptEncoder;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
DAOUser user = userDao.findByUsername(username);
if (user == null){
throw new UsernameNotFoundException("User not found with username: " + username);
}
return new User(user.getUsername(), user.getPassword(), new ArrayList<>());
}
public DAOUser save(UserDTO user) {
DAOUser newUser = new DAOUser();
newUser.setUsername(user.getUsername());
newUser.setPassword(bcryptEncoder.bCryptPasswordEncoder().encode(user.getPassword()));
return userDao.save(newUser);
}
}
My WebSecurityConfig:
#Configuration
#AllArgsConstructor
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {//provides security for endpoints
#Autowired
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
#Autowired
private UserDetailsService jwtUserDetailsService;
#Autowired
private JwtRequestFilter jwtRequestFilter;
private final AccountService accountService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// configure AuthenticationManager so that it knows from where to load
// user for matching credentials
// Use BCryptPasswordEncoder
auth.userDetailsService(jwtUserDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()//So we can send post requests without being rejected(if we using form based indication we want to enable this)
.authorizeRequests()
.antMatchers("/authenticate","/register")
.permitAll()//any request that goes trough that end point we want to allow.
.anyRequest()
.authenticated().and().exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(daoAuthenticationProvider());
}
#Bean
public DaoAuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider provider =
new DaoAuthenticationProvider();
provider.setPasswordEncoder(bCryptPasswordEncoder);
provider.setUserDetailsService(accountService);
return provider;
}
}
My RequestFilter:
#Component
public class JwtRequestFilter extends OncePerRequestFilter {
#Autowired
private JwtUserDetailsService jwtUserDetailsService;
#Autowired
private JwtTokenUtil jwtTokenUtil;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws ServletException, IOException {
final String authorizationHeader = request.getHeader("Authorization");
String username = null;
String jwt = null;
if (authorizationHeader != null && authorizationHeader.startsWith("")){
jwt = authorizationHeader.substring(7);
username = jwtTokenUtil.extractUsername(jwt);
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null){
UserDetails userDetails = this.jwtUserDetailsService.loadUserByUsername(username);
if (jwtTokenUtil.validateToken(jwt, userDetails)){
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
usernamePasswordAuthenticationToken
.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
}
}
chain.doFilter(request, response);
}
}
My PasswordEncoder:
#Configuration
public class PasswordEncoder{
#Bean
public BCryptPasswordEncoder bCryptPasswordEncoder(){
return new BCryptPasswordEncoder();
}
}
My UserDao
#Entity
#Table(name = "myusers")
public class DAOUser {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
#Column
private String username;
#Column
#JsonIgnore
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
My UserDao Interface
I know the name is confusing, but I just followed the tutorial and he gave it this name, I have not changed it, because I want it to work before I rename files.
#Repository
public interface UserDao extends CrudRepository<DAOUser, Integer> {
DAOUser findByUsername(String username);
}
I think these are all the files you need to help me. if you need more, just ask and I will upload them.
Can anyone help me with this problem?
Thanks!!
if you read the spring documentation on passwords (which you should of done before you ask here)
you will see that the format when storing a password is:
{bcrypt}$2a$10$dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM/BG
While when you are storing it you are just storing it and not adding the {bcrypt} prefix to the generated string before you store it.
newUser.setPassword(bcryptEncoder.bCryptPasswordEncoder().encode(user.getPassword()));
So when you are later providing a password, you are getting bad password since spring does not know what encoder to use when decoding the password.

Spring security UserDetails and controller (get user)

There is UserDetail and LoginController.
UserDetail gets the user from the database.
UserDetail
public class UserDetail implements UserDetailsService {
private final
UserServiceJpa userServiceJpa;
public UserDetail(UserServiceJpa userServiceJpa) {
this.userServiceJpa = userServiceJpa;
}
#Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
// Get user
User user = userServiceJpa.findUserByEmail(email);
if (user == null){
throw new UsernameNotFoundException("There is no such user " + email);
}
return new org.springframework.security.core.userdetails.User(user.getEmail(),
user.getPassword(),
user.getEnabled(),
user.getAccount_non_expired(),
user.getCredentials_non_expired(),
user.getAccount_non_locked(),
getAuthorities());
}
private Collection<? extends GrantedAuthority> getAuthorities(){
List<SimpleGrantedAuthority> authList = new ArrayList<>();
authList.add(new SimpleGrantedAuthority("ROLE_USER"));
authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
return authList;
}
}
LoginController
#Controller
public class LoginController {
#GetMapping(value = "/login")
public String login () {
return "/login";
}
}
Question! How in LoginController get this user, which was received by UserDetail?
I do this in order not to reconnect to the database. Thus, I want to know how the user was blocked if he was blocked - enabled, accountNonExpired, credentialsNonExpired, accountNonLocked
You can create a UserDetails class from your LoginController by Autowiring it, and then call the function in your login class.
#Controller
public class LoginController {
#Autowired
private UserDetails userDetails;
#GetMapping(value = "/login")
public String login (#QueryParam("email")String email) {
userDetails.loadUserByUsername(email);
return "/login";
}
}

There is no PasswordEncoder mapped for the id "null" with database authentication

I successfully build in-memory authentication. But when I going to build it with database comes this error.
There is no PasswordEncoder mapped for the id "null"
This is followed tutorial - Spring Boot Tutorial for Beginners, 10 - Advanced Authentication using Spring Security | Mighty Java
There are classes
SpringSecurityConfiguration.java
#Configuration
#EnableWebSecurity
public class SpringSecurityConfiguration extends
WebSecurityConfigurerAdapter{
#Autowired
private AuthenticationEntryPoint entryPoint;
#Autowired
private MyUserDetailsService userDetailsService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().httpBasic()
.authenticationEntryPoint(entryPoint);
}
}
AuthenticationEntryPoint.java
#Configuration
public class AuthenticationEntryPoint extends BasicAuthenticationEntryPoint{
#Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.addHeader("WWW-Authenticate", "Basic realm -" +getRealmName());
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
PrintWriter writer = response.getWriter();
writer.println("Http Status 401 "+authException.getMessage());
}
#Override
public void afterPropertiesSet() throws Exception {
setRealmName("MightyJava");
super.afterPropertiesSet();
}
}
MyUserDetailsService .java
#Service
public class MyUserDetailsService implements UserDetailsService{
#Autowired
private UserRepository userRepository;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if(user == null){
throw new UsernameNotFoundException("User Name "+username +"Not Found");
}
return new org.springframework.security.core.userdetails.User(user.getUserName(),user.getPassword(),getGrantedAuthorities(user));
}
private Collection<GrantedAuthority> getGrantedAuthorities(User user){
Collection<GrantedAuthority> grantedAuthority = new ArrayList<>();
if(user.getRole().getName().equals("admin")){
grantedAuthority.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
grantedAuthority.add(new SimpleGrantedAuthority("ROLE_USER"));
return grantedAuthority;
}
}
UserRepository interface
public interface UserRepository extends JpaRepository<User, Long>{
#Query("FROM User WHERE userName =:username")
User findByUsername(#Param("username") String username);
}
Role.java
#Entity
public class Role extends AbstractPersistable<Long>{
private String name;
#OneToMany(targetEntity = User.class , mappedBy = "role" , fetch = FetchType.LAZY ,cascade = CascadeType.ALL)
private Set<User> users;
//getter and setter
}
User.java
#Entity
public class User extends AbstractPersistable<Long>{
//AbstractPersistable class ignore primary key and column annotation(#Column)
private String userId;
private String userName;
private String password;
#ManyToOne
#JoinColumn(name = "role_id")
private Role role;
#OneToMany(targetEntity = Address.class, mappedBy = "user",fetch= FetchType.LAZY ,cascade =CascadeType.ALL)
private Set<Address> address; //Instead of Set(Unordered collection and not allow duplicates) we can use list(ordered and allow duplicate values) as well
//getter and setter}
If you have any idea plese inform. Thank you.
I changed MyUserDetailsService class adding passwordEncoder method.
Added lines
BCryptPasswordEncoder encoder = passwordEncoder();
Changed Line
//changed, user.getPassword() as encoder.encode(user.getPassword())
return new org.springframework.security.core.userdetails.User(--)
MyUserDetailsService.java
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
BCryptPasswordEncoder encoder = passwordEncoder();
User user = userRepository.findByUsername(username);
if(user == null){
throw new UsernameNotFoundException("User Name "+username +"Not Found");
}
return new org.springframework.security.core.userdetails.User(user.getUserName(),encoder.encode(user.getPassword()),getGrantedAuthorities(user));
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
As from Spring Security 5.x, Spring Security enforces you to use a password encoder if you're working with other than in-memory (production) databases.
Spring Security enforces this by activating the default DelegatingPasswordEncoder, which looks for PasswordEncoder beans.
By adding a BCryptPasswordEncoder, the DelegatingPasswordEncoder will return that instance to encrypt passwords.
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
I don't recommend you to do this, but if you really want to, you can override password encoding by adding {noop} to the password value.
This will treat the password by activating the NoOpPasswordEncoder instead of the default DelegatingPasswordEncoder and will treat your password as plain text.
Please note that this is not recommended if you deploy your app to a production environment!

Manually set Authenticated Spring User

I am building a SpringBoot application.
I am using Spring Security, and have a UserDetailsService implementation setup:
public class MyUserDetailService implements UserDetailsService {
#Autowired
private UserService userService;
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
org.springframework.security.core.userdetails.User springUser = null;
User user = userService.loadUserByUsername(username);
if(user != null){
List<SimpleGrantedAuthority> authorities = null;
List<Role> roles = user.getRoles();
if(roles != null){
authorities = new ArrayList<>();
for(Role currentRole: roles){
authorities.add(new SimpleGrantedAuthority(currentRole.name()));
}
}
springUser = new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
}
return springUser;
}
}
I have a service layer that contains method for adding users to the database:
public interface UserService {
public Long addStandardUser(String firstName, String lastName, String username, String password);
#PreAuthorize("hasRole('ADMIN')")
public Long addAdministratorUser(String firstName, String lastName, String username, String password);
#PreAuthorize("hasRole('ADMIN')")
public User loadUserByUsername(String username);
public Iterable<User> getUsers(int pageNumber, int pageSize, Direction direction, String sort);
}
I also have a CommandLineRunner implementation that I use (in dev mode) to initialize the database with sample users:
#Component
#Profile("dev")
public class DBInitializer implements CommandLineRunner {
#Autowired
private UserService userService;
#Override
public void run(String... args) throws Exception {
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ADMIN"));
Authentication authentication = new UsernamePasswordAuthenticationToken("foo", null, authorities);
SecurityContextHolder.getContext().setAuthentication(authentication);
userService.addAdministratorUser("John", "Doe", "jdoe", "1234");
System.out.println("done!");
}
}
The trouble is that I am getting an Access Denied exception from Spring in the CommandLineRunner when I try to add the user. I'm assuming that the issue is that I am manually 'injecting' a Spring User incorrectly. The addAdminUser() method has to be run by a user in the ADMIN role, so I need to temporarily run as an ADMIN user. I know there is a #RunAs annotation that I remember using in other J2EE apps, but I'm not sure how that interfaces with a Spring application, or if that is used in a different context altogether
...
// The default role prefix starts with `ROLE_`
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
...
More detail please see here

Java + Spring MVC + Hibernate Persistence Error - Cant Persist User [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Ok so I am building an ecommerce site using java spring mvc, spring security, maven, hibernate, and some other technologies however those should be the only ones relevant to my problem. I am doing all java config with no XML by the way (which I am currently considering revising since I am running into situations where xml just seems easier).
I would like to know why I am getting an no exceptions upon maven install but getting exceptions on server restart (tomcat 7).
I have tried to get this down to as simple as possible while still having a user and a role. When I am looking at the code, it really is pretty straight forward stuff - I am dying to find out why it errors out everytime.
Main Appconfig class
#EnableWebMvc
#Configuration
#ComponentScan({ "com.crutchsf.*" })
#EnableTransactionManagement
#Import({ SecurityConfig.class })
public class AppConfig {
#Bean
public SessionFactory sessionFactory() {
LocalSessionFactoryBuilder builder = new LocalSessionFactoryBuilder(dataSource());
builder
.scanPackages("com.crutchsf.users.model")
.addProperties(getHibernateProperties());
return builder.buildSessionFactory();
}
private Properties getHibernateProperties() {
Properties prop = new Properties();
prop.put("hibernate.format_sql", "true");
prop.put("hibernate.show_sql", "true");
prop.put("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
return prop;
}
#Bean(name = "dataSource")
public BasicDataSource dataSource() {
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/test");
ds.setUsername("bobby");
ds.setPassword("password");
return ds;
}
#Bean
public HibernateTransactionManager txManager() {
return new HibernateTransactionManager(sessionFactory());
}
#Bean
public UserService userService() {
UserService userService = new MyUserDetailsService();
userService.setUserDao(new UserDaoImpl());
return userService;
}
#Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("validation");
return messageSource;
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/pages/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/img/**").addResourceLocations("/img/").setCachePeriod(31556926);
}
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
SecurityConfig.java
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("userDetailsService")
UserDetailsService userDetailsService;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/admin/**")
.access("hasRole('ROLE_ADMIN')").and().formLogin()
.loginPage("/login").failureUrl("/login?error")
.usernameParameter("username")
.passwordParameter("password")
.and().logout().logoutSuccessUrl("/login?logout")
.and().csrf()
.and().exceptionHandling().accessDeniedPage("/403");
}
}
User class
#Entity
#Table(name = "users", catalog = "test")
public class User {
private Integer user_id;
private String username;
private String password;
private String passwordConf;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
#Id
#Column(name = "user_id")
#GeneratedValue
public Integer getUserId() {
return this.user_id;
}
#Column(name = "username", unique = true, nullable = false, length = 45)
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
#Column(name = "password", nullable = false, length = 60)
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
#Transient
public String getPasswordConf() {
return this.passwordConf;
}
public void setPasswordConf(String passwordConf) {
this.passwordConf = passwordConf;
}
}
UserRole class
#Entity
#Table(name = "user_roles", catalog = "test",
uniqueConstraints = #UniqueConstraint(
columnNames = { "role", "username" }))
public class UserRole{
private Integer userRoleId;
private User user;
private String role;
public UserRole() {
}
public UserRole(User user, String role) {
this.user = user;
this.role = role;
}
#Id
#GeneratedValue(strategy = IDENTITY)
#Column(name = "user_role_id",
unique = true, nullable = false)
public Integer getUserRoleId() {
return this.userRoleId;
}
public void setUserRoleId(Integer userRoleId) {
this.userRoleId = userRoleId;
}
public User getUser() {
return this.user;
}
public void setUser(User user) {
this.user = user;
}
#Column(name = "role", nullable = false, length = 45)
public String getRole() {
return this.role;
}
public void setRole(String role) {
this.role = role;
}
}
UserDao Interface
public interface UserDao {
User findByUserName(String username);
List<User> findAllUsers();
void addUser(User user);
}
UserDaoImpl
#Repository
public class UserDaoImpl implements UserDao {
#Autowired
private SessionFactory sessionFactory;
#SuppressWarnings("unchecked")
public User findByUserName(String username) {
List<User> users = new ArrayList<User>();
users = sessionFactory.getCurrentSession().createQuery("from User where username=?").setParameter(0, username)
.list();
if (users.size() > 0) {
return users.get(0);
} else {
return null;
}
}
#Override
#Transactional
public void addUser(User user) {
sessionFactory.getCurrentSession().persist(user);
}
UserService Interface
public interface UserService {
UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException;
void setUserDao(UserDao userDao);
void addUser(com.crutchsf.model.users.User user);
}
User Service Impl
#Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService, UserService {
#Autowired
private UserDao userDao;
#Transactional(readOnly=true)
#Override
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException {
com.crutchsf.model.users.User user = userDao.findByUserName(username);
List<GrantedAuthority> authorities = buildUserAuthority(user.getUserRole());
return buildUserForAuthentication(user, authorities);
}
private User buildUserForAuthentication(com.crutchsf.model.users.User user, List<GrantedAuthority> authorities) {
return new User(user.getUsername(), user.getPassword(), user.isEnabled(), true, true, true, authorities);
}
private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
// Build user's authorities
for (UserRole userRole : userRoles) {
setAuths.add(new SimpleGrantedAuthority(userRole.getRole()));
}
List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths);
return Result;
}
#Override
#Transactional
public void addUser(com.crutchsf.model.users.User user) {
this.userDao.addUser(user);
}
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
}
Database SQL used
CREATE TABLE users (
user_id int(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(45) NOT NULL UNIQUE,
PRIMARY KEY (user_id));
Ok I shortened this quite a bit to the simple task of persisting a user. I cant get the server to startup without errors. There has to be something wrong in the code above.
In AppConfig.java if I change the line "scanPackages...." to the actual class name
com.crutchsf.users.model.User
then my server starts up fine but when it reaches the line in my userDao to be persisted
sessionFactory.getCurrentSession().persist(user);
I get a different error from hibernate "Cant find entity com.crutchsf.users.model.User"
Here is the main error I get. Basically I can choose which error I want to get now.
[public org.hibernate.SessionFactory com.crutchsf.config.AppConfig.sessionFactory()] threw exception; nested exception is java.lang.NullPointerException
thank you
On the surface, this doesn't appear to be anything to do with Spring MVC or Hibernate.
The error message is:
Factory method [public org.hibernate.SessionFactory com.crutchsf.config.AppConfig.sessionFactory()] threw exception; nested exception is java.lang.NullPointerException
If you have a stacktrace, you'll be able to see exactly what line the null reference occurred on. If not, you'll have to fire up a debugger (or insert println statements) to find out.
Either way, it appears that your AppConfig class has a bug in it, or you are not initialising it correctly. Look at the sessionConfig() method to see why it NPEs, and ensure that the appropriate references are not null before calling it.

Categories

Resources