• 导入依赖

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
  • 配置数据源

    # 数据源
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.username=root
    spring.datasource.password=root
    spring.datasource.url=jdbc: mysql://localhost:3306/songs?serverTimezone=UTC
    # 别名
    mybatis.type-aliases-package=com.xiang.entity
    # mapper路径
    mybatis.mapper-locations=classpath:com.xiang.dao/*.xml
  • 编写实体类

    // Lombok
    @Data
    public class User implements UserDetails{
          private String username;
          private String password;
          @Override
          public Collection<? extends GrantedAuthority> getAuthorities() {
              return null;
          }
          @Override
          public boolean isAccountNonExpired() {
              return true;
          }
          @Override
          public boolean isAccountNonLocked() {
              return true;
          }
    
          @Override
          public boolean isCredentialsNonExpired() {
              return true;
          }
          @Override
          public boolean isEnabled() {
              return true;
          }
    }
  • 接口

    @Mapper
    public interface UserMapper {
              void AddUser(@Param("username") String username,@Param("password") String password);
              User findOneByUsername(@Param("username") String username);
    }
  • 在resources目录下创建与dao接口包名相同的目录,并创建UserMapper.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
          PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
          "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.xiang.dao.UserMapper">
              <insert id="AddUser">
                  insert into users(username,password) values(#{username},#{password});
              </insert>
              <select id="findOneByUsername" resultType="user">
                  select username,password from users where username=#{username};
              </select>
    </mapper>
  • 编写service层

    @Service
    public class UserService implements UserDetailsService{
          @Autowired
          private UserMapper userMapper;
    
          @Autowired
          private PasswordEncoder passwordEncoder;
    
          public boolean register(User user){
              //保存到数据库
              try{
                  userMapper.AddUser(user.getUsername(),passwordEncoder.encode(user.getPassword()));
              }catch (Exception e){
                  System.out.println(e.fillInStackTrace());
                  return false;
              }
              return true;
          }
    
          @Override
          public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
              return userMapper.findOneByUsername(username);
          }
    }
  • 编写controller层

  • 编写Spring Security配置类

    • 重写configure(HttpSecurity http)方法配置拦截策略
      @Configuration
      public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
            @Bean
            public PasswordEncoder passwordEncoder(){
                return new BCryptPasswordEncoder();
            }
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http
                    .authorizeRequests()
                        .antMatchers("/user/registerPage","/user/register","/user/loginPage","/user/login").permitAll()
                        .anyRequest().authenticated()
                    .and()
                    .httpBasic()
                    .and()
                    .formLogin()
                        .loginPage("/user/loginPage") //登录页面url
                        .loginProcessingUrl("/user/login") //登录表单的action路径
                        //登录成功后的路径,默认返回templates目录下的index.html页面
                        .defaultSuccessUrl("/user/index")//登录成功后跳转的路径.successForwardUrl("/user/index")登录成功后重定向的路径
                        .and()
                        .logout()
                            .logoutUrl("/user/logout")
                            .logoutSuccessUrl("/user/loginPage");
            }
      }
  • 编写注册页面、登录页面

    • 注册页面主要部分
      <form th:action="@{/user/register}" method="post">
            <!--如果开启了CSRF防护功能,需要添加一个隐藏的域,才可以使用post方式提交,否则会被拦截 -->
            <input type="hidden" name="_csrf" value="af53a1c2-b2b0-4f92-9907-80555a2329ac">
            <input type="text" name="username">
            <input type="password" name="password">
            <input type="submit" value="Register">
      </form>
  • 登录页面主要部分

    <form th:action="@{/login}" method="post">
              <input type="text" name="username">
              <input type="password" name="password">
              <input type="submit" value="Login in">
    </form>
  • 退出页面主要部分

    <form th:action="@{/user/logout}" method="post">
              <input type="submit" value="Logout">
    </form>
    • Spring Security3.2开始,默认开启CSRF(跨站请求伪造)防护。通过一个同步token来实现CSRF防护功能,会拦截状态变化的请求并检查CSRF token:如果请求中不包含token或者token与服务器不匹配的话,请求就会失败。
    • 所有的post请求必须在一个"_csrf"域中提交token。
      在form标签中使用th:action="@{/user/register}"设置提交路径,就会自动生成一个"_csrf"隐藏域。
  • 关闭CSRF防护功能(不推荐)

    http.csrf().disable();//禁用CSRF防护功能