一、简介
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包:
org.springframework.boot
spring-boot-starter-security
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') ;