1. 程式人生 > >初探Spring Security

初探Spring Security

一、簡介

Spring Security是Spring社群的一個頂級專案,也是 Spring Boot官方推薦使用的Security框架。除了常規的 Authentication和Authorization之外,Spring Security還 提供了諸如ACLs,LDAP,JAAS,CAS等高階特性以滿足複雜場景下的安全需求

二、理解

1、從AAA說起

【中文名稱】:鑑權、授權和計費

【英文名稱】:Authentication, Authorization and Accounting

【英文縮寫】:AAA

2、Authentication是怎麼回事?

在AAA體系中是沒有ROLE的,ROLE=ONE Special Authority OR Some Related Authorities Group
 2、Role與Authority

Role=擁有一組許可權( Authority/Permission)的某種人(Principle) 

粗粒度的設計1:一種角色就用一個Authority表示,

比如: Authorities={ROLE_ADMIN},

表示管理員角色 Authorities={ROLE_USER},表示普通使用者角色

Authorities={ROLE_USER, ROLE_ADMIN},表示雙重身份的使用者角色

粗粒度的設計2:一種角色就用表示角色本身名字的Authority,以及對應的具體的許可權的Authority 來表示,比如: Authorities={ROLE_ADMIN,OP_CreateUser,OP_Drop_User,OP_FrozenUser},表示管理員角色,擁有三種特定的許可權 Authorities={ROLE_USER,OP_ChangePassword,OP_List_Reports},表示普通使用者角色,有兩個許可權

3、Spring Security Authentication 

 

三、實際使用

1、依賴jar包:

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
		</dependency>

 2、實現基本登入

@Configuration
public class BasicSecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests().antMatchers("/admin/**")
		.authenticated()
		.and().formLogin().permitAll();
	}

	@Override
	public void configure(WebSecurity web) throws Exception {
		web.ignoring().antMatchers("**/js/**", "**/css/**", "**/images/**", "**/**/favicon.ico");

	}

}

 3、jdbc 登入配置

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.JdbcUserDetailsManager;
import org.springframework.security.provisioning.UserDetailsManager;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;

import leader.utils.PasswordHash;

@EnableGlobalMethodSecurity(prePostEnabled = true) //啟用全域性方法驗證
@Configuration
public class JDBCSecurityConfig extends WebSecurityConfigurerAdapter {
	
	@Autowired
	private DataSource datasource ;
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		JdbcTokenRepositoryImpl repository = getTokenRepository() ;
                /*禁用 csrf 驗證方式*/
		http.csrf().disable() ; 
                /*登入退出匹配的url*/
		//.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                // 訪問 /manager/createuser 時需要op_createuser角色
                // 訪問/manager/** 時需要manager角色
		http.authorizeRequests().antMatchers("/manager/createuser").hasAnyRole("op_createuser")
		.antMatchers("/manager/**").hasAnyRole("manager")
		.and().formLogin().permitAll().and() 
                                 /*讓瀏覽器啟用記住我,開啟後 登入頁面 啟用記住我按鈕*/
				.rememberMe().tokenRepository( repository ).tokenValiditySeconds(31536000).and()
				.logout().permitAll().and(); 
	}
	/**把記住我改成 jdbc連結方式進行驗證*/
	public JdbcTokenRepositoryImpl getTokenRepository() {
		JdbcTokenRepositoryImpl r = new JdbcTokenRepositoryImpl();
		r.setDataSource(datasource);
		return r;
	}
	@Override
	public void configure(WebSecurity web) throws Exception {
                /*配置 js css images 等不需要進行登入攔截*/
		web.ignoring().antMatchers("**/js/**", "**/css/**", "**/images/**", "**/**/favicon.ico");

	}
	@Override
	public void configure(AuthenticationManagerBuilder auth) throws Exception {
                /**指定使用者登入使用的方式,指定密碼加密的方式,這裡用 PasswordHash 方式加密,可以自己更改為MD5,或者PBE方式*/
		auth.userDetailsService(jdbcUserDetailsManager()).passwordEncoder(new PasswordEncoder() {
			@Override
			public boolean matches(CharSequence rawPassword, String encodedPassword) {
                                /*驗證密碼是否正確, rawPassword 登入輸入的密碼,encodedPassword 是資料庫中儲存的密碼 */
				return ((String)rawPassword).equals(encodedPassword);
			}
			@Override
			public String encode(CharSequence rawPassword) {
                                 /*對註冊的密碼進行加密*/
				return (String) rawPassword;
			}
		});
	}
        /**啟用jdbc 登入,需要建立 user表,表結構在後面給出*/
	public UserDetailsManager jdbcUserDetailsManager() throws Exception {
		JdbcUserDetailsManager userMan = new JdbcUserDetailsManager();
		userMan.setDataSource(datasource);
		userMan.setRolePrefix("ROLE_");
		return userMan;
	}
}

 4、表結構建立

DROP TABLE IF EXISTS  users ;

CREATE TABLE users (
  username VARCHAR(20) NOT NULL,
  PASSWORD VARCHAR(150) NOT NULL,
  enabled TINYINT(1) DEFAULT NULL,
  PRIMARY KEY (username)
) ENGINE=INNODB DEFAULT CHARSET=utf8 ;

DROP TABLE IF EXISTS authorities;
CREATE TABLE authorities (
  id BIGINT(20) NOT NULL AUTO_INCREMENT,
  username VARCHAR(20) NOT NULL,
  authority VARCHAR(50) NOT NULL,
  PRIMARY KEY (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS persistent_logins ;
CREATE TABLE persistent_logins (
  id INT(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  username VARCHAR(50) DEFAULT '' COMMENT 'username',
  series VARCHAR(50) DEFAULT '' COMMENT 'series',
  token VARCHAR(64) DEFAULT '' COMMENT 'tokenValue',
  last_used DATETIME DEFAULT NULL COMMENT 'last_used',
  KEY id (id),
  KEY series (series)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
-- user leader , password : 123456
INSERT INTO users(username,PASSWORD,enabled)VALUES('leader' , '123456' , 1) ; 
INSERT authorities(username,authority)VALUES('admin' , 'admin') ;