Spring Security簡(jiǎn)介
Spring Security 是專門(mén)針對(duì)基于Spring的項(xiàng)目安全框架,充分利用了依賴注入和AOP來(lái)實(shí)現(xiàn)安全的功能母赵,安全框架主要用的是認(rèn)證(Authentication)和授權(quán)(Authorization)小槐。
SpringBoot 對(duì)其的支持
關(guān)于Spring Security 的自動(dòng)配置在SpringBoot 中在org.springframework.boot.autoconfigure.security包中
關(guān)于在SpringBoot中配置Spring Security 包含下圖這樣
當(dāng)我們需要使用自己的擴(kuò)展配置時(shí)需要自己的類實(shí)現(xiàn)WebSecurityConfigurerAdapter類即可
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
UserDetailsService customUserService(){
return new CustomUserService();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserService());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.permitAll()
.and()
.logout()
.permitAll();
}
}
實(shí)戰(zhàn)
- 首先添加pom文件 。這里使用的mysql 數(shù)據(jù)庫(kù)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.21</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
- 在application.properties中配置好數(shù)據(jù)庫(kù)鏈接
spring.jpa.database=mysql
spring.datasource.url=jdbc:MySQL://localhost:3306/com_study
spring.datasource.username = root
spring.datasource.password=111111
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.jackson.srialization.indent_output=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
debug=true
logging.level.org.springframework.security= INFO
spring.thymeleaf.cache=false
- 定義實(shí)現(xiàn)我們的實(shí)體bean
@Entity
public class SysUser implements UserDetails{
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private Long id;
private String userName;
private String password;
@ManyToMany(cascade = {CascadeType.REFRESH},fetch = FetchType.EAGER)
private List<SysRole> roles;
public static long getSerialVersionUID() {
return serialVersionUID;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> auths=new ArrayList<GrantedAuthority>();
List<SysRole> roles=this.getRoles();
for(SysRole role:roles){
auths.add(new SimpleGrantedAuthority(role.getName()));
}
return auths;
}
@Override
public String getPassword() {
return null;
}
@Override
public String getUsername() {
return null;
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return false;
}
@Override
public boolean isCredentialsNonExpired() {
return false;
}
@Override
public boolean isEnabled() {
return false;
}
public List<SysRole> getRoles() {
return roles;
}
public void setRoles(List<SysRole> roles) {
this.roles = roles;
}
}
@Entity
public class SysRole {
@Id
@GeneratedValue
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- 添加配置文件web和Security配置
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter{
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
}
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
UserDetailsService customUserService(){
return new CustomUserService();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserService());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error")
.permitAll()
.and()
.logout()
.permitAll();
}
}
- 實(shí)現(xiàn)service 并且dao層實(shí)現(xiàn)jpa
public interface SysUserRepository extends JpaRepository<SysUser,Long> {
SysUser findByUserName(String userName);
}
public class CustomUserService implements UserDetailsService {
@Autowired
private SysUserRepository sysUserRepository;
@Override
public UserDetails loadUserByUsername(String username) {
SysUser user=sysUserRepository.findByUserName(username);
if(user==null){
throw new UsernameNotFoundException("用戶名不存在");
}
return user;
}
}
- 添加我們的頁(yè)面的登錄頁(yè)面login.html
總結(jié)
我們?cè)趯?shí)現(xiàn)安全驗(yàn)證內(nèi)容的時(shí)候,首先需要實(shí)現(xiàn)我們需要的WebSecurityConfigurerAdapter 然后我們重寫(xiě)我們config 方法烟央,在代碼Security配置中我們?cè)O(shè)置權(quán)限訪問(wèn)anyRequest 任何訪問(wèn)頁(yè)面的路徑都需要先登錄驗(yàn)證后才可以洼滚。如果不想每個(gè)頁(yè)面都得登錄才可以訪問(wèn),我們可以自己定制匹配路徑可以在http.authorizeRequests()中使用antMatcher("/user/index")或者regexMatchers("/user/index"),更多配置方式可以看Spring的頁(yè)面皮璧。