springboot security

 

源碼下載地址:http://git.oschina.net/alan_rcw/springboot-secrutiy/widgethtml

1、	整合Spring Security

在pom.xml中加入以下片斷:
<dependency>
       			 <groupId>org.springframework.security</groupId>
        			 <artifactId>spring-security-web</artifactId>
        </dependency>
		
		 <dependency>
    				<groupId>org.springframework.security</groupId>
   				 <artifactId>spring-security-config</artifactId>
  		</dependency>

2、	配置Spring Security

幾乎全部配置都在下面這個文件中完成:

@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	@Autowired
	private CustomUserDetailsService customUserDetailsService;//code1
	
	@Autowired @Qualifier("dataSource1")
	private DataSource dataSource1; //code2


	@Override
	protected void configure(HttpSecurity http) throws Exception {
		//容許全部用戶訪問」/」和」/home」
		http.authorizeRequests().antMatchers("/", "/home").permitAll()
        //其餘地址的訪問均需驗證權限
		.anyRequest().authenticated()
		.and()
		.formLogin()
		//指定登陸頁是」/login」
		.loginPage("/login")		
		.permitAll()
		//登陸成功後可以使用loginSuccessHandler()存儲用戶信息,可選。
		.successHandler(loginSuccessHandler())//code3
		.and()
		.logout()
//退出登陸後的默認網址是」/home」
		.logoutSuccessUrl("/home")
		.permitAll()
		.invalidateHttpSession(true)
		.and()
		//登陸後記住用戶,下次自動登陸
        //數據庫中必須存在名爲persistent_logins的表
        //建表語句見code15
		.rememberMe()
		.tokenValiditySeconds(1209600)
		//指定記住登陸信息所使用的數據源
		.tokenRepository(tokenRepository());//code4
	
	}

	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {	
//指定密碼加密所使用的加密器爲passwordEncoder()
//須要將密碼加密後寫入數據庫 //code13
	auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());//code5
//不刪除憑據,以便記住用戶
		auth.eraseCredentials(false);		
	}
	
	// Code5----------------------------------------------
	@Bean
	public BCryptPasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder(4);
	}

	// Code4----------------------------------------------
	@Bean
	public JdbcTokenRepositoryImpl tokenRepository(){		
		JdbcTokenRepositoryImpl j=new JdbcTokenRepositoryImpl();
		j.setDataSource(dataSource1);
		return j;
	}

	// Code3----------------------------------------------
	@Bean
	public LoginSuccessHandler loginSuccessHandler(){
		return new LoginSuccessHandler();//code6
	}
}

code1----------------------------------------------

@Component
public class CustomUserDetailsService implements UserDetailsService {
	@Autowired  //數據庫服務類
	private SUserService suserService;//code7

	@Override
	public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
        //SUser對應數據庫中的用戶表,是最終存儲用戶和密碼的表,可自定義
        //本例使用SUser中的email做爲用戶名:
		SUser user = suserService.findUserByEmail(userName); //code8
		if (user == null) {
			throw new UsernameNotFoundException("UserName " + userName + " not found");
		}
		// SecurityUser實現UserDetails並將SUser的Email映射爲username
		return new SecurityUser(user); //code9
	}
}



Code2----------------------------------------------


@Configuration
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class })
public class MyConfiguration {

	@Bean
	public DataSource dataSource1() {

		org.springframework.jdbc.datasource.DriverManagerDataSource ds = new org.springframework.jdbc.datasource.DriverManagerDataSource();
		ds.setDriverClassName("com.mysql.jdbc.Driver");
		ds.setUrl("jdbc:mysql://localhost:3306/test");
		ds.setUsername("root");
		ds.setPassword("****");
		return ds;
	}
}

Code6----------------------------------------------
//能夠在這裏將用戶登陸信息存入數據庫。
public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler{  
    
    @Override  
    public void onAuthenticationSuccess(HttpServletRequest request,  
            HttpServletResponse response, Authentication authentication) throws IOException,  
            ServletException {  
        //得到受權後可獲得用戶信息   可以使用SUserService進行數據庫操做
        SUser userDetails = (SUser)authentication.getPrincipal();  
          
        //輸出登陸提示信息  
        System.out.println("管理員 " + userDetails.getEmail() + " 登陸");  
    	
        System.out.println("IP :"+getIpAddress(request));
              
        super.onAuthenticationSuccess(request, response, authentication);  
    }  
    
    public String getIpAddress(HttpServletRequest request){    
        String ip = request.getHeader("x-forwarded-for");    
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {    
            ip = request.getHeader("Proxy-Client-IP");    
        }    
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {    
            ip = request.getHeader("WL-Proxy-Client-IP");    
        }    
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {    
            ip = request.getHeader("HTTP_CLIENT_IP");    
        }    
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {    
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");    
        }    
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {    
            ip = request.getRemoteAddr();    
        }    
        return ip;    
    }  
      
}

Code7----------------------------------------------

@Service("suserService")
public class SUserService {

	@Autowired
	private SUserRepository suserRepository;//code10

	public List<SUser> findAll() {
		return suserRepository.findAll();
	}

	public SUser create(SUser user) {
		return suserRepository.save(user);
	}

	public SUser findUserById(int id) {
		return suserRepository.findOne(id);
	}

	public SUser login(String email, String password) {
		return suserRepository.findByEmailAndPassword(email, password);
	}

	public SUser update(SUser user) {
		return suserRepository.save(user);
	}

	public void deleteUser(int id) {
		suserRepository.delete(id);
	}

	public SUser findUserByEmail(String email) {
		return suserRepository.findUserByEmail(email);
	}

}

Code8----------------------------------------------
@Entity
@Table(name = "s_user", catalog = "test")//code11
public class SUser implements java.io.Serializable {

	private Integer id;
	private String name;
	private String email;
	private String password;
	private Date dob;
	private Set<SRole> SRoles = new HashSet<SRole>(0);// Code12

	public SUser() {
	}

	public SUser(String name, String email, String password, Date dob, Set<SRole> SRoles) {
		this.name = name;
		this.email = email;
		this.password = password;
		this.dob = dob;
		this.SRoles = SRoles;
	}

	@Id
	@GeneratedValue(strategy = IDENTITY)

	@Column(name = "id", unique = true, nullable = false)
	public Integer getId() {
		return this.id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	@Column(name = "name", length = 20)
	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Column(name = "email", length = 20)
	public String getEmail() {
		return this.email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@Column(name = "password", length = 20)
	public String getPassword() {
		return this.password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	@Temporal(TemporalType.DATE)
	@Column(name = "dob", length = 10)
	public Date getDob() {
		return this.dob;
	}

	public void setDob(Date dob) {
		this.dob = dob;
	}

	@OneToMany(fetch = FetchType.EAGER, mappedBy = "SUser")
	public Set<SRole> getSRoles() {
		return this.SRoles;
	}

	public void setSRoles(Set<SRole> SRoles) {
		this.SRoles = SRoles;
	}

}

Code9----------------------------------------------

public class SecurityUser extends SUser implements UserDetails
{

	private static final long serialVersionUID = 1L;
	public SecurityUser(SUser suser) {
		if(suser != null)
		{
			this.setId(suser.getId());
			this.setName(suser.getName());
			this.setEmail(suser.getEmail());
			this.setPassword(suser.getPassword());
			this.setDob(suser.getDob());
			this.setSRoles(suser.getSRoles());
		}		
	}
	
	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		
		Collection<GrantedAuthority> authorities = new ArrayList<>();
		Set<SRole> userRoles = this.getSRoles();
		
		if(userRoles != null)
		{
			for (SRole role : userRoles) {
				SimpleGrantedAuthority authority = new SimpleGrantedAuthority(role.getName());
				authorities.add(authority);
			}
		}
		return authorities;
	}

	@Override
	public String getPassword() {
		return super.getPassword();
	}

	@Override
	public String getUsername() {
		return super.getEmail();
	}

	@Override
	public boolean isAccountNonExpired() {
		return true;
	}

	@Override
	public boolean isAccountNonLocked() {
		return true;
	}

	@Override
	public boolean isCredentialsNonExpired() {
		return true;
	}

	@Override
	public boolean isEnabled() {
		return true;
	}
	
}
Code10----------------------------------------------
public interface SUserRepository extends JpaRepository<SUser, Integer> {
	@Query("select u from SUser u where u.email=?1 and u.password=?2")
	SUser login(String email, String password);

	SUser findByEmailAndPassword(String email, String password);

	SUser findUserByEmail(String email);
}

Code11----------------------------------------------
SUser對應的表和角色表,一個都不能少
CREATE TABLE `s_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `email` varchar(20) DEFAULT NULL,
  `password` varchar(60) DEFAULT NULL,
  `dob` date DEFAULT NULL,
  PRIMARY KEY (`id`)
)
 

CREATE TABLE `s_role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `uid` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `userrole` (`uid`),
  CONSTRAINT `userrole` FOREIGN KEY (`uid`) REFERENCES `s_user` (`id`)
)

 

Code12----------------------------------------------
@Entity
@Table(name = "s_role", catalog = "test")
public class SRole implements java.io.Serializable {

	private Integer id;
	private SUser SUser;
	private String name;

	public SRole() {
	}

	public SRole(SUser SUser) {
		this.SUser = SUser;
	}

	public SRole(SUser SUser, String name) {
		this.SUser = SUser;
		this.name = name;
	}

	@Id
	@GeneratedValue(strategy = IDENTITY)

	@Column(name = "id", unique = true, nullable = false)
	public Integer getId() {
		return this.id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "uid", nullable = false)
	public SUser getSUser() {
		return this.SUser;
	}

	public void setSUser(SUser SUser) {
		this.SUser = SUser;
	}

	@Column(name = "name", length = 20)
	public String getName() {
		return this.name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

Code13----------------------------------------------
@SpringBootApplication
public class Application {

	@SuppressWarnings("unchecked")
	public static void main(String[] args) {
		SpringApplication app=new SpringApplication(Application.class);		
				
		Appctx.ctx=app.run(args);//將密碼加密 必須保證數據庫s_user中有id爲1的用戶//code14
SUserService suserService = (SUserService) Appctx.ctx.getBean("suserService");
        SUser su= suserService.findUserById(1);
        BCryptPasswordEncoder bc=new BCryptPasswordEncoder(4);
        su.setPassword(bc.encode("111111"));
        suserService.update(su);
}	

Code14----------------------------------------------
public class Appctx { 
    public static ApplicationContext ctx=null; 
    public static Object getObject(String string){
    	return ctx.getBean(string);
    }
}	

Code15----------------------------------------------
//請勿手工寫入數據 供remember-me功能使用
CREATE TABLE `persistent_logins` (
  `username` varchar(64) NOT NULL,
  `series` varchar(64) NOT NULL,
  `token` varchar(64) NOT NULL,
  `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`series`)
)

Code15----------------------------------------------
public interface SRoleRepository extends JpaRepository<SRole,Integer> {

}

3、	Html及controller

index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>Insert title here</title>
</head>
<body>
Welcome to Spring technology page!
</body>
</html>



hello.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Hello World!</title>
    </head>
    <body>
        <h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>
        <form th:action="@{/logout}" method="post">
            <input type="submit" value="Sign Out"/>
        </form>
    </body>
</html>

home.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security Example</title>
    </head>
    <body>
        <h1>Welcome!</h1>
        
        <p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
    </body>
</html>



login.html

本頁中 username password remember-me三個控件請勿更名。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
    <head>
        <title>Spring Security Example </title>
    </head>
    <body>
        <div th:if="${param.error}">
            Invalid username and password.
        </div>
        <div th:if="${param.logout}">
            You have been logged out.
        </div>
        <div th:if="${#httpServletRequest.remoteUser != null}">
    <p th:text="${#httpServletRequest.remoteUser}">
      sample_user
    </p>
</div>
        <form th:action="@{/login}" method="post">
            <div><label> User Name : <input type="text" name="username"/> </label></div>
            <div><label> Password: <input type="password" name="password"/> </label></div>
            <div><input type="submit" value="Sign In"/></div>
            <input type="checkbox" name="remember-me" value="true" th:checked="checked"/><p>Remember me</p>
        </form>
    </body>
</html>







Controller:


@Controller
@RequestMapping("/")
public class GreetingController {


@RequestMapping("/home")
	public String home() {
		return "home";
	}

	@RequestMapping("/hello")
	public String hello() {
		SecurityContext   ctx   =   SecurityContextHolder.getContext();              
        Authentication   auth   =   ctx.getAuthentication();                    
        if(auth.getPrincipal()   instanceof   UserDetails)      
        {      
        	SUser    user   =   (SUser)auth.getPrincipal();          
            System.out.println(user.getEmail());                            
        }              
         //本段代碼演示如何獲取登陸的用戶資料    
        
		return "hello";
	}
	
	@RequestMapping("/")
	public String root() {
    //如不進行此項配置,從login登陸成功後,會提示找不網頁
		return "index";
	}



}

4、    構建及運行順序
1.    首先創建s_user s_role表,並向表中寫入數據
2.    創建SUserService SUserRepository SUser  SRoleRepository SRole類
3.    運行程序,將s_user中用戶的密碼加密
4.    如三中所述,配置Spring Security
5.    運行,訪問http://localhost:8080/hello,系統出現以下界面:
 
用戶名輸入useremail  密碼輸入111111,點sign in則進入hello.html
 
重啓瀏覽器,再訪問http://localhost:8080/hello,則無需登陸,直接到達。
在hello頁面點sign out後,則返回home頁面,退出了登陸。java

相關文章
相關標籤/搜索