简介
整合下springboot与security,通过二者简单的搭建一个登录访问的权限控制,话不多说直接上实战
HellWord
导入pom依赖
<!-- 添加springsecurity依赖 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
</dependency>
由于我之前添加了springboot的父类所以这里只需要直接导入组名和依赖名称就可以了
启动你的项目
你会发现项目的接口都添加了访问控制.看一下控制台
Using default security password: a800db21-c227-49a3-85f6-2b5434c67ab2
有这样的一行代码输出,说明了默认的用户名和密码
User user = this.securityProperties.getUser();
if (user.isDefaultPassword()) {
logger.info(String.format("%n%nUsing default security password: %s%n",
user.getPassword()));
}
通过这段代码可以看到在控制台输出了一个日志,密码是从user中取出来的,进入user中查看一下果然
private String name = "user";
private String password = UUID.randomUUID().toString();
默认用户名为user,密码是通过uuid自动生成的.
security:
user:
name: admin
password: admin
role: admin
用户名和密码可以再application中自定义,也可以在重写configure方法或者绑定数据库来定义
优化你的security
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.antMatchers("/resources/**", "/signup", "/about").permitAll()
.antMatchers("/admin/**").hasRole("admin")
.antMatchers("/db/**").access("hasRole('admin') and hasRole('dba')")
.and()
.formLogin()
.loginPage("/security/toLogin")
.loginProcessingUrl("/security/login")
.successForwardUrl("/security/success/login")
.failureForwardUrl("/security/false")
.and()
.logout()
.logoutUrl("/security/logout")
.logoutSuccessUrl("/security/success/logout")
.and()
.exceptionHandling().accessDeniedPage("/security/denied")
.and()
.rememberMe()
.key("jbzm-Security")
.rememberMeCookieName("cookieName")
.rememberMeParameter("paramName")
.tokenRepository(new InMemoryTokenRepositoryImpl());
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin").password("admin").roles("admin")
.and()
.withUser("dba").password("dba").roles("dba", "admin");
}
}
下面开始分析这段代码
添加@EnableWebSecurity
@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
@Target(value = { java.lang.annotation.ElementType.TYPE })
@Documented
@Import({ WebSecurityConfiguration.class,
SpringWebMvcImportSelector.class })
@EnableGlobalAuthentication
@Configuration
- 这是@EnableWebSecurity的注解构成,比较明显,自动导入bean,以及可以当做配置文件
继承WebSecurityConfigurerAdapter
- 通过继承该方法来添加security的控制
- 这里需要重写他的三个方法
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().and()
.httpBasic();
- 这是在默认情况下security默认加载的,其中formLogin就是默认添加的登录验证模块
一个坑csrf
- CSRF(Cross-site request forgery跨站请求伪造,也被称为“One Click Attack” 或者Session Riding,攻击方通过伪造用户请求访问受信任站点。
http
.csrf().and() <- 这里添加了csrf验证
.addFilter(new WebAsyncManagerIntegrationFilter())
.exceptionHandling().and()
.headers().and()
- 简而言之就是跨域访问的问题,security4.0之后会默认开启csrf安全验证,需要我们手动去关闭.
添加访问权限
.requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.antMatchers("/resources/**", "/signup", "/about").permitAll()
.antMatchers("/admin/**").hasRole("admin")
.antMatchers("/db/**").access("hasRole('admin') and hasRole('dba')")
- 添加cors跨域验证,以及对应权限允许开放的访问地址
这是测试代码
@RestController
public class TestLoginController {
@GetMapping("lol")
public Object testLol() {
return "成功/lol";
}
@GetMapping("resources/lol")
public Object testResources() {
return "成功/resources";
}
@GetMapping("admin/lol")
public Object testAdmin() {
return "成功/admin";
}
@GetMapping("db/lol")
public Object testDba() {
return "成功/db";
}
}
设置登录/登出跳转
.formLogin()
.loginPage("/security/toLogin")
.loginProcessingUrl("/security/login")
.successForwardUrl("/security/success/login")
.failureForwardUrl("/security/false")
.and()
.logout()
.logoutUrl("/security/logout")
.logoutSuccessUrl("/security/success/logout")
- logPage是登录页面
- 由于前后台分离,通过返回json来告知前台跳转登录页
- loginProcessingUrl
- 填写验证登录的请求地址
- successForwardUrl
- 填写成功后跳转的地址,同样通过json告知前台登录成功
- failureForwardUrl
- 登录失败调调专路径,同上使用json
登出功能同理,不做解释了,下面是测试用的接口,测试登录
@RestController
public class Test {
@GetMapping("lol")
public Object testLol() {
return "成功";
}
@GetMapping("resources/lol")
public Object testResources() {
return "成功";
}
@GetMapping("admin/lol")
public Object testAdmin() {
return "成功";
}
@GetMapping("db/lol")
public Object testDba() {
return "成功";
}
}
添加权限不足跳转,以及cookie保存
.exceptionHandling().accessDeniedPage("/security/denied")
.and()
.rememberMe()
.key("jbzm-Security")
.rememberMeCookieName("cookieName")
.rememberMeParameter("paramName")
.tokenRepository(new InMemoryTokenRepositoryImpl());
- 这里不做过多介绍了,很好理解