天天看点

【Spring Boot】Spring Security的使用一、配置Spring Security环境二、Spring Security

文章目录

  • 一、配置Spring Security环境
  • 二、Spring Security
    • 1.怎样配置Security
    • 2.授权
    • 3.认证
    • 4.注销
    • 5.自定义登录页面
    • 6.RememberMe功能

一、配置Spring Security环境

  1. 新建工程:参考文章【Spring Boot】快速上手SpringBoot
  2. 导入Spring Security的依赖pom.xml:
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
           

我们还会用到Thymeleaf引擎:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
           
  1. 项目结构:
    【Spring Boot】Spring Security的使用一、配置Spring Security环境二、Spring Security
  2. 首页:index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div align="center">
    <h1>首页</h1>
    <table>
        <tr>
            <td>登录</td>
            <td><a th:href="@{/to_login}">访问</a> </td>
            <td>注销</td>
            <td><a th:href="@{/logout}">访问</a></td>
        </tr>
        <tr>
            <td>VIP1</td>
            <td><a th:href="@{/vip1/1}">访问1</a> </td>
            <td><a th:href="@{/vip1/2}">访问2</a> </td>
            <td><a th:href="@{/vip1/3}">访问3</a> </td>
        </tr>
        <tr>
            <td>VIP2</td>
            <td><a th:href="@{/vip2/1}">访问1</a> </td>
            <td><a th:href="@{/vip2/2}">访问2</a> </td>
            <td><a th:href="@{/vip2/3}">访问3</a> </td>
        </tr>
        <tr>
            <td>VIP3</td>
            <td><a th:href="@{/vip3/1}">访问1</a> </td>
            <td><a th:href="@{/vip3/2}">访问2</a> </td>
            <td><a th:href="@{/vip3/3}">访问3</a> </td>
        </tr>
    </table>
</div>
</body>
</html>
           
  1. controller类:RouterController.java
@Controller
public class RouterController {

    @RequestMapping({"/","/index"})
    public String index(){
        return "index";
    }

    @RequestMapping("/to_login")
    public String login(){
        return "views/login";
    }

    @RequestMapping("/vip1/{id}")
    public String vip1(@PathVariable int id){
        return "views/vip1/"+id;
    }

    @RequestMapping("/vip2/{id}")
    public String vip2(@PathVariable int id){
        return "views/vip2/"+id;
    }

    @RequestMapping("/vip3/{id}")
    public String vip3(@PathVariable int id){
        return "views/vip3/"+id;
    }
}
           
  1. 页面:对应的VIP才可以访问其他页面,规定角色,我们需要用到Spring Security
【Spring Boot】Spring Security的使用一、配置Spring Security环境二、Spring Security

二、Spring Security

官方解释:

Spring Security is a framework that provides authentication, authorization, and protection against common attacks. With first class support for both imperative and reactive applications, it is the de-facto standard for securing Spring-based applications.

Spring Security是一个提供身份验证、授权和针对常见攻击的保护的框架。它对命令式和反应式应用程序都提供了一流的支持,是保护基于spring的应用程序的事实标准。

官网地址:https://docs.spring.io/spring-security/site/docs/5.4.1/reference/html5/

1.怎样配置Security

官方示例:@EnableWebSecurity和继承WebSecurityConfigurerAdapter

【Spring Boot】Spring Security的使用一、配置Spring Security环境二、Spring Security

2.授权

重写方法:

protected void configure(HttpSecurity http) throws Exception

SecurityConfig.java

@EnableWebSecurity  //开启WebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //链式编程
        http.authorizeRequests().antMatchers("/").permitAll()
                .antMatchers("/vip1/**").hasRole("vip1")
                .antMatchers("/vip2/**").hasRole("vip2")
                .antMatchers("/vip3/**").hasRole("vip3");

        http.formLogin();
    }
}
           
【Spring Boot】Spring Security的使用一、配置Spring Security环境二、Spring Security

这里的登录页面是Security自带的:

【Spring Boot】Spring Security的使用一、配置Spring Security环境二、Spring Security

3.认证

重写方法:

protected void configure(AuthenticationManagerBuilder auth) throws Exception

写在SecurityConfig.java中

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("gaolang").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2")
                .and()
                .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3");
    }
           
【Spring Boot】Spring Security的使用一、配置Spring Security环境二、Spring Security

用户root可以访问vip1、vip2和vip3下的访问。

用户gaolang可以访问vip1和vip2下的访问,访问vip3下时为ErrorPage:

【Spring Boot】Spring Security的使用一、配置Spring Security环境二、Spring Security

但是实际情况是这些用户来自数据库,而不是自己定义:

数据库身份认证:

导入相关依赖:参考文章:【Spring Boot】数据库连接和Druid使用

  1. 首先连上我们的数据库
  2. 数据库中user表:
    【Spring Boot】Spring Security的使用一、配置Spring Security环境二、Spring Security
  3. 建好与数据库表相应的实体类
  4. 实现一些方法:

    User getUserByName(String name);

  5. 写一个Service类继承接口UserDetailsService
@Component
public class CustomUserDetailService implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;


    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
       //通过name===》获得这个User
        User user = userMapper.getUserByName(s);
        if (user == null){
            throw new UsernameNotFoundException("用户不存在");
        }

        //取出角色
        String roles = user.getRoles();

        //角色集合
        List<GrantedAuthority> grantedAuthorities = new ArrayList<>();

        //必须以ROLE_开头
        grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_"+roles));

        return new org.springframework.security.core.userdetails.User(user.getName(),
                new BCryptPasswordEncoder().encode(user.getPwd()),grantedAuthorities);
    }
}
           
  1. 完整的SecurityConfig类:
@EnableWebSecurity  //开启WebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomUserDetailService userDetailsService;

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //链式编程
        http.authorizeRequests().antMatchers("/","/get_auth").permitAll()
                .antMatchers("/vip1/**").hasRole("vip1")
                .antMatchers("/vip2/**").hasRole("vip2")
                .antMatchers("/vip3/**").hasRole("vip3");

        http.formLogin();
        http.logout().logoutSuccessUrl("/to_login");
       // http.rememberMe();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        /*auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("gaolang").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2")
                .and()
                .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3");*/
        auth
                .userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder());
    }
}
           

4.注销

加在授权的方法中,logoutSuccessUrl是指注销后跳转到的页面,这里是首页

在前端需要使用注销时,设置a标签:/login和/logout都时Security提供的

5.自定义登录页面

Spring Security自定义了login页面,我们不用它的,用自己的:

修改SecurityConfig.java里面的授权代码:

http.formLogin().loginPage("/to_login").passwordParameter("pwd").usernameParameter("user");

两个input标签,对应 用户名和密码 ,两个标签的name属性分别为user和pwd

http.formLogin().loginPage("/to_login");

不设置其他的,从源码可以看出name属性是默认是username和password

【Spring Boot】Spring Security的使用一、配置Spring Security环境二、Spring Security

login.html:

th:action="@{/to_login}"

这个action就是返回我们的login.html对应loginPage("/to_login")

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
    <h1 align="center">登录页面</h1>
    <form th:action="@{/to_login}" method="post">
        用户名:<input type="text" name="user">
        密码:<input type="text" name="pwd">
        <input type="submit" value="提交">
    </form>
</div>
</body>
</html>
           

6.RememberMe功能

  1. 我们没有设置自己的登录页面,使用Security提供的:

    在SecurityConfig.java里面的授权代码中添加:

    http.rememberMe();

  2. 设置了自己的登录页面:
<input type="checkbox" name="remember">记住我
           

在SecurityConfig.java里面的授权代码中添加:

http.rememberMe().rememberMeParameter("remember");