认证和授权学习2:springboot中快速使用spring security
本文以一个示例工程记录下如何在springboot工程中快速的使用spring security,使用的springboot版本是
2.1.3.RELEASE
一、创建工程,导入依赖
创建一个springboot工程,导入springsecurity的起步依赖.
<!-- 以下是>spring boot依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 以下是>spring security依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
二、默认配置
这个时候启动应用,这个应用就已经被保护了,springsecurity提供了一个默认用户user
,对应的密码在启动工程时会打印在控制台上,如
Using generated security password: c07618df-93d6-4d0c-88df-9c373d2131e3
这个时候访问应用中的一个资源,就会跳转到springsecurity默认的一个登录页面,输入账号密码后会跳转到登录前要访问的url
三、自定义配置
主要涉及2个方面,用户配置,安全配置,通过创建一个配置类继承WebSecurityConfigurerAdapter
来配置
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//1.用户配置
//2.安全配置
}
3.1用户配置
配置时springsecurity提供了两种用户配置,简单点的可以直接在内存中配置用户对象,用于测试;也可以连接数据库进行持久化配置
3.1.1 在内存中配置用户
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//1.用户配置
@Bean
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withUsername("lyy").password("123").authorities("ROLE_p1").build());
manager.createUser(User.withUsername("zs").password("123").authorities("ROLE_ADMIN").build());
return manager;
}
//1.1用户密码的加密方式
@Bean
public PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
//return new BCryptPasswordEncoder();
}
//2.安全配置
}
springsecurity提供了一个InMemoryUserDetailsManager
对象来在内存中创建用户。在上边的代码中,创建了两个用户并赋予不同的权限。
需要注意的是,要配置验证用户密码时使用的加密方式,如果不想加密,可以配置NoOpPasswordEncoder
的对象,表示不加密。
3.1.2 使用数据库中的用户对象
springsecurity提供了一个UserDetailsService
接口来查询用户,要从数据库查询用户,只需要创建一个这个接口的bean并加入spring容器中,然后移除内存用户的相关配置,但编码器还要保留。
@Component
public class MyUserDetailService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//模拟从数据库查询用户信息,这里这个UserDetails中的用户信息都是从数据库查询到的
System.out.println("当前请求登录的用户:"+username);
UserDetails userDetails = User.withUsername(username).password("111")
.authorities("p1").build();
return userDetails;
}
}
实际上就是实现了loadUserByUsername方法,返回了一个UserDetails对象给springsecurity
3.2安全配置
安全配置通过重写configure方法来实现。主要设置这几个方面
(1)哪些url被保护,需要什么权限才能访问。这里要注意的是,用hasRole指定角色时不带ROLE_
前缀,但是配置用户时要带上ROLE_
前缀。匹配url时,越具体的url要先匹配。
(2)配置登录页面和处理登录请求的url,注意自定义安全配置时一定要把登录页面和登录url配上,不然访问任何页面都是403,除非最后一行调用父类的config方法
(3)退出和失效的相关配置.
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//1.用户配置
...
//2.安全配置
@Override
protected void configure(HttpSecurity http) throws Exception {
/**
* 设置对url的保护时,更具体的规则应该先写,模糊匹配的要写在最后,
* 因为一次请求匹配到第一个规则后就会忽略后边的规则
*/
http.csrf().disable();
//这两个资源要有特定的权限才可以访问
http.authorizeRequests().antMatchers("/r/r1").hasRole("p1");
http.authorizeRequests().antMatchers("/r/r2").hasRole("p2");
//配置这个目录下的资源要登录才可以访问,不配置的话不拦截,不登录页可以访问
http.authorizeRequests().antMatchers("/r/**").authenticated();
http.authorizeRequests().anyRequest().permitAll();
//因为下边这个配置针对的url在上边那个配置已经匹配过了,所以下边这个不生效
http.authorizeRequests().antMatchers("/test1.html").authenticated();
http.formLogin()
.loginPage("/login.html")
//处理登录请求的url
.loginProcessingUrl("/login");
//登录成功后的跳转url,如果不配置,默认跳转到登录前要访问的页面
//.successForwardUrl("/login-success");
//这个配置配置的是多个人登录同一账号时,后边的把前边的挤掉后,把前边的重定向到的页面
http.sessionManagement().maximumSessions(1).expiredUrl("/sessionExpired.html");
//这个配置退出的url和退出后跳转到的页面
http.logout().logoutUrl("/mylogout").logoutSuccessUrl("/logoutSuccess.html");
}
}
注意这里所有的html页面都放在springboot的静态资源目录中,这样才能被访问到,我是放在了resources/static
目录。
登录页面的内容如下
<html>
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
login
<form action="login" method="post">
用户名:<input type="text" name="username"><br>
密 码:
<input type="password" name="password"><br>
<input type="submit" value="登录">
</form>
</body>
</html>
注意这里登录表单的action写的是相对路径,如果要写绝对路径,就要带上当前应用的路径,即yml中的配置
server:
port: 8080
servlet:
context-path: /springsecurity-springboot01
可以在这里查看完整的示例工程