simple
简单的SpringSecurity部署,仅从内存里配置用户数据。
项目源码gitte地址: https://gitee.com/xiang_Gitee/spring-security-learn(子工程simple)
推荐博文:
手把手带你入门 Spring Security!
Spring Security 入门原理及实战
干货|一个案例学会Spring Security 中使用 JWT
必要依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
实际上添加好依赖之后,配置好application.yml和启动类,不做其他配置SpringSecurity就已经生效,会在后台控制台上打印密码(用户名默认为user)
访问http://localhost:端口号 的任何url都会跳转到框架默认自带的登录页面
当然这是远不能满足我们需求的,需要进一步配置
简单配置
首先添加一个用以演示的控制器:
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "登录成功";
}
@GetMapping("/home")
public String home() {
return "首页成功,未登录噢";
}
@GetMapping("/signin")
public String login() {
return "请先登录";
}
@GetMapping("/error")
public String error() {
return "登录失败";
}
}
security配置类:
SecurityConfig 继承WebSecurityConfigurerAdapter 进行配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//认证需求路径
http.authorizeRequests()
.antMatchers("/", "/home")//添加ant风格的url匹配
.permitAll()//上面两个url全部允许(放行)
.anyRequest()//任何请求url
.authenticated();//都需要验证
//登录配置
http.formLogin()
.failureUrl("/error")//登录错误跳转
.defaultSuccessUrl("/hello")//登录成功跳转
.permitAll();//全部放行
//登出配置
http.logout()
.logoutSuccessUrl("/home")//登出成功跳转
.logoutUrl("/logout");//登出url
}
/**
* 生成一个内存用户
* @return
*/
@Bean
@Override
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()//处于演示可用,生产环境由于不安全而不建议使用
.username("user")
.password("password")
.build();
return new InMemoryUserDetailsManager(user);
}
}
在这个配置类中,做了两件事:
1. 覆盖configure(HttpSecurity http) 方法,规定了哪些url可以直接访问,其余需要验证之后访问,规定了登录的跳转页面。
2. 覆盖UserDetailsService userDetailsService()方法并注册为Bean,在里面手动生成了一个UserDetails,用户名为"user"密码为“password”,.withDefaultPasswordEncoder()
表示密码不加密,InMemoryUserDetailsManager
表示存入内存。
UserDetails是SpringSecurity中用以存储账户信息的类,UserDetailsService是用以获取UserDetails的接口,后面就是继承这个接口实现从数据库获取用户信息。
现在访问http://localhost:8080/hello,配置中除了"/", "/home"的url访问都需要验证,所以会跳转到默认的登录接口/login,也就是默认的登录页面,输入正确用户名和密码点击Sign 登录成功,访问/hello
自定义登录url
现在修改SecurityConfig的configure(HttpSecurity http)方法:
@Override
protected void configure(HttpSecurity http) throws Exception {
//认证需求路径
http.authorizeRequests()
.antMatchers("/", "/home")//添加ant风格的url匹配
.permitAll()//上面两个url全部允许(放行)
.anyRequest()//任何请求url
.authenticated();//都需要验证
//登录路径
http.formLogin()
.loginPage("/signin")
.loginProcessingUrl("/dosignin")
.failureUrl("/error")//登录错误跳转
.defaultSuccessUrl("/hello")//登录成功跳转
.permitAll();//全部放行
//登出路径
http.logout()
.logoutSuccessUrl("/home")//登出成功跳转
.logoutUrl("/logout");//登出url
}
在登录配置那里加了两行配置.loginPage("/signin")
:
登录界面,任何未登录的请求都会跳转到这个url,若controller未配置对应url,会默认跳转到一开始的那个html登陆界面,而此处若未配置url,则会默认跳转至"/login".loginProcessingUrl("/dosignin")
:
登录接口,通过这个接口实现登录,此处若未配置url,则会将loginPage设置的url(post方法)作为登录路径。
SpringSecurity的登录处理并不是通过配置Controller来进行登录,而是通过Filter,具体方法在下篇文章记录
如此配置好后,登录跳转就会转到/signin
通过postman访问/dosignin
结果:总之就是失败了
在之前的自带登录html里可以看到登录请求时除了用户名和密码之外还有一个隐藏参数_csrf,这个参数的具体原因在这里:spring security CSRF防护
在请求的时候带上_csrf参数即可,这里选择直接关闭这个默认配置:
重新运行访问
最终配置
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 设置通过拦截器保护请求
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();//禁用跨域保护策略csrf。csrf默认开启,这样就得在登录时加个_csrf参数,演示环境可以禁用
//认证需求路径
http.authorizeRequests()
.antMatchers("/", "/home")//添加ant风格的url匹配
.permitAll()//上面两个url全部允许(放行)
.anyRequest()//任何请求url
.authenticated();//都需要验证
//登录路径
http.formLogin()
.loginPage("/signin")//登录界面,未登录会跳转到这个url,若controller未配置对应url,会默认跳转一个的html登陆界面
.loginProcessingUrl("/dosignin")//登录接口,通过这个接口实现登录,若未设置,则会将loginPage的设置url作为默认登录接口
.failureUrl("/error")//登录错误跳转
.defaultSuccessUrl("/hello")//登录成功跳转
.permitAll();//全部放行
//登出路径
http.logout()
.logoutSuccessUrl("/home")//登出成功跳转
.logoutUrl("/logout");//登出url
}
/**
* 生成一个内存用户
* @return
*/
@Bean
@Override
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()//处于演示可用,生产环境由于不安全而不建议使用
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}