引言
Spring家族庞大,每一块都像教科书般典范,这篇文章旨在学习和了解spring security,内容逐渐补充。
1 spring security概念
spring security有一块比较大的内容,23大章的内容可不是盖的。 最新5.1.1的官方文档在这里 ,各种版本可以看这里。
2 spring security应用
初步应用看起来比较简单,在springboot下,只要引入一个maven依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
然后准备一个config类:
package com.seaever.qingdu.config;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;
import javax.sql.DataSource;
//https://www.cnblogs.com/softidea/p/5991897.html
//https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-security.html
//https://docs.spring.io/spring-security/site/docs/5.1.1.RELEASE/reference/htmlsingle/#jc-method
@Configuration
@EnableGlobalMethodSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired AccessDeniedHandler accessDeniedHandler;
@Autowired private DataSource dataSource;
public static void main(String[] args) {
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
//加密"0"
String encode = bCryptPasswordEncoder.encode("admin");
System.out.println(encode);
//结果:$2a$10$/eEV4X7hXPzYGzOLXfCizu6h7iRisp7I116wPA3P9uRcHAKJyY4TK
}
//https://stackoverflow.com/questions/24174884/spring-security-jdbcauthentication-default-scheme-error-on-postgresql
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.dataSource(dataSource)
//https://www.jianshu.com/p/9e7792d767b2
.passwordEncoder(new BCryptPasswordEncoder())
//.withDefaultSchema()
.usersByUsernameQuery(
"select username,password, enabled from users where username=?")
.authoritiesByUsernameQuery(
"select username, role from user_roles where username=?");
//.withUser(User.withDefaultPasswordEncoder().username("user").password("password").roles("USER"));
}
// @Override
// public void configure(WebSecurity web) throws Exception {
// getHttp()
// .csrf().disable()
// .exceptionHandling()
// //.authenticationEntryPoint(unauthorizedHandler)
// .accessDeniedHandler(accessDeniedHandler)
// .and()
// .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
// .and()
// .authorizeRequests()
// .antMatchers("/actuator/**").permitAll()
// .antMatchers("/actuator/**").hasAuthority("ADMIN")
// .antMatchers(
// HttpMethod.GET,
// "/v2/api-docs"
// ,"/swagger-resources/**"
// ,"/swagger-ui.html**"
// //,"/webjars/**"
// //, "favicon.ico"
// ).permitAll()
// .antMatchers("/auth/**").permitAll()
// //.anyRequest().authenticated()
// ;
//
//// http
//// .addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class)
//// .headers()
//// .cacheControl();
// }
}
这里用的是mysql数据库来存储用户信息,需要用到两个表:
CREATE TABLE `users` (
`username` varchar(20) NOT NULL,
`password` varchar(60) NOT NULL,
`enabled` tinyint(1) NOT NULL,
PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `user_roles` (
`username` varchar(20) NOT NULL,
`role` varchar(20) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
数据表中的password
内容是一个通过BCryptPasswordEncoder运算的加密串。user_roles
没有主键,username
一对多也没问题,如果这个表里没记录,
权限马上会失效,比如刷新页面:http://localhost:8080/swagger-ui.html
,莫不是每次都会查数据库?
现在权限验证通过了,如果配置哪些需要验证,一直没生效,待了解。下列跳过的配置有效:
@Override
public void configure(WebSecurity web) {
web.ignoring()
.antMatchers(
"/swagger-resources/**"
,"/swagger-ui.html**"
);
}
官方的测试示例