Spring security +Hibernate+UserDetailsService認證

定義數據庫表:users和user_roles:
CREATE TABLE `users` (
  `username` varchar(45) NOT NULL,
  `password` varchar(60) NOT NULL,//如果使用BCryptPasswordEncoder加密,必須使長度大於60
  `enabled` tinyint(1) NOT NULL,
  PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE `user_roles` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(45) NOT NULL,
  `role` varchar(45) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `username` (`username`),
  CONSTRAINT `username` FOREIGN KEY (`username`) REFERENCES `users` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1

定義User model:

package com.users.model;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name="users")
public class User {
	@Id
	@Column(name="username",unique=true,nullable=false,length=45)
	private String username;
	@Column(name="password",nullable=false,length=60)
	private String password;
	@Column(name="enabled",nullable=false)
	private boolean enabled;
	@OneToMany(fetch=FetchType.LAZY,mappedBy="user")
	private Set<UserRole> userRole=new HashSet<UserRole>(0);
	
	public User(){}
	
	public User(String username,String password,boolean enabled){
		this.username=username;
		this.password=password;
		this.enabled=enabled;
	}
	
	public User(String username,String password,boolean enabled,Set<UserRole> userRole){
		this.username=username;
		this.password=password;
		this.enabled=enabled;
		this.userRole=userRole;
	}
	

	public String getUsername(){
		return this.username;
	}
	public void setUsername(String username){
		this.username=username;
	}
	
	public String getPassword(){
		return this.password;
	}
	public void setPassword(String password){
		this.password=password;
	}
	

	public boolean isEnabled(){
		return this.enabled;
	}
	public void setEnabled(boolean enabled){
		this.enabled=enabled;
	}
	

	public Set<UserRole> getUserRole(){
		return this.userRole;
	}
	public void setUserRole(Set<UserRole> userRole){
		this.userRole=userRole;
	}
}
定義UserRole model:

package com.users.model;

import static javax.persistence.GenerationType.AUTO;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

@Entity
@Table(name="user_roles",uniqueConstraints=@UniqueConstraint(
		columnNames={"role","username"}))
public class UserRole {
	@Id
	@GeneratedValue(strategy=AUTO)
	@Column(unique=true,nullable=false)
	private Integer id;
	@ManyToOne(fetch=FetchType.LAZY)
	@JoinColumn(name="username",nullable=false)
	private User user;
	@Column(nullable=false,length=45)
	private String role;
	
	public Integer getId(){
		return this.id;
	}
	public void setId(Integer id){
		this.id=id;
	}
	
	public User getUser(){
		return this.user;
	}
	public void setUser(User user){
		this.user=user;
	}
	
	public String getRole(){
		return this.role;
	}
	public void setRole(String role){
		this.role=role;
	}
	
}

定義數據訪問接口並使用Hibernate實現:

import com.users.model.User;

public interface UserDao {
	User findByUserName(String username);
}
package com.users.dao;

import javax.inject.Inject;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.users.model.User;

@Repository
public class UserDaoImpl implements UserDao {
	private SessionFactory sessionFactory;
	@Inject
	public UserDaoImpl(SessionFactory sessionFactory){
		this.sessionFactory=sessionFactory;
	}
	public Session currentSession(){
		return sessionFactory.openSession();
	}
	
	public User findByUserName(String username){
		return (User)currentSession().createCriteria(User.class).add(Restrictions.eq("username",username)).list().get(0);//簡單處理,list()=null?
	}
}
實現UserDetailsService接口:

package com.users.service;


import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.users.dao.UserDao;
import com.users.model.UserRole;


@Service("userDetailsService")//在SecurityConfig中自動匹配/注入
public class UserService implements UserDetailsService{
	
	@Autowired
	private UserDao userDao;
	
	@Transactional(readOnly=true)
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		<span style="color:#FF0000;">com.users.model.User</span> user=userDao.findByUserName(username);//<span style="color:#FF0000;">與org.springframework.security.core.userdetails.User重名,最好修改爲不同</span>
		List<GrantedAuthority> authorities=buildUserAuthority(user.getUserRole());
		return buildUserForAuthentication(user,authorities);
	}
	
	private User buildUserForAuthentication(com.users.model.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>();
		for(UserRole userRole:userRoles){
			setAuths.add(new SimpleGrantedAuthority(userRole.getRole()));
		}
		List<GrantedAuthority> result=new ArrayList<GrantedAuthority>(setAuths);
		return result;
	}
	
}

配置SecurityConfig:

	......
        @Autowired
	@Qualifier("userDetailsService")
	UserDetailsService  userDetailsService;
        ....
	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
		//auth.inMemoryAuthentication().withUser("ram").password("ram123").roles("ADMIN");
		auth.userDetailsService(userDetailsService);
		//.passwordEncoder(passwordEncoder()); 
	}	
	
	@Bean
	public PasswordEncoder passwordEncoder(){
		PasswordEncoder encoder=new BCryptPasswordEncoder();
		return encoder;
	}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章