一文搞懂SpringSecurity---[Day03]自定义登录逻辑+自定义登录页面

496 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。


当 进 行 自 定 义 登 录 逻 辑 时 需 要 用 到 之 前 讲 解 的 UserDetailsServicePasswordEncoder 。但是

Spring Securit要求:当进行自定义登录逻辑时容器内必须有 PasswordEncoder 实例。所以不能直接 new 对象。

编写配置类

``

@Configuration
public class SecurityConfig {
    @Bean
    public PasswordEncoder getPw(){
        return new BCryptPasswordEncoder();
    }
}
自定义逻辑

Spring Security 中实现 UserDetailService 就表示为用户详情服务。在这个类中编写用户认证逻辑。

``

/**
 * 自定义登录逻辑
 *
 * @author 爪哇小白2021
 * @date 2022/06/30
 */
@Service
public class UserServiceImpl implements UserDetailsService {
    @Autowired
    private PasswordEncoder pw;
​
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        /**
         * 查询数据库判断用户名是否存在,如果不存在抛出UsernameNotFoundException异常
         * 为了简单直接模拟数据
         */
        if (!"admin".equals(username)){
            throw new UsernameNotFoundException("用户名不存在");
        }
        /**
         * 把查询出来的密码(注册时已经加密过)进行解析,或直接把密码放入构造方法中
         */
        String password = pw.encode("123");
        return new User(username,password,
                AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal"));
    }
}
查看效果

重启项目后,在浏览器中输入账号:admin,密码:123。后可以正确进入到 login.html 页面。

image.png

自定义登录页面

自定义登录页面

虽然 Spring Security 给我们提供了登录页面,但是对于实际项目中,大多喜欢使用自己的登录页面。所以 Spring Security 中不仅仅提供了登录页面,还支持用户自定义登录页面。实现过程也比较简单,只需要修改配置类即可。

编写登录页面

login.html

``

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login" method="post">
    用户名:<input type="text" name="username" /><br/>
    密码:<input type="password" name="password" /><br/>
    <input type="submit" value="登录" />
</form>
</body>
</html>
修改配置类

修改配置类中主要是设置哪个页面是登录页面。

配置类需要继承WebSecurityConfigurerAdapte,并重写 configure方法。

  • successForwardUrl() :登录成功后跳转地址
  • loginPage() :登录页面
  • loginProcessingUrl :登录页面表单提交地址,此地址可以不真实存在。
  • antMatchers() :匹配内容
  • permitAll() :允许

``

package com.example.spring.config;
​
​
import com.example.spring.service.impl.UserServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
​
/**
 * 安全配置
 *
 * @author 爪哇小白2021
 * @date 2022/06/30
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
​
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //表单提交
        http.formLogin()
                //自定义登录页面
                .loginPage("/login.html")
                //当发现/login时认为是登录,必须和表单提交的地址一样。去执行UserServiceImpl
                .loginProcessingUrl("/login")
                //登录成功后跳转页面,POST请求
                .successForwardUrl("/toMain");
        http.authorizeRequests()
                //login.html不需要被认证
                .antMatchers("/login.html").permitAll()
                //所有请求都必须被认证,必须登录后被访问
                .anyRequest().authenticated();
        //关闭csrf防护
        http.csrf().disable();
    }
    
    @Bean
    public PasswordEncoder getPw(){
        return new BCryptPasswordEncoder();
    }
​
}
编写控制器

``

package com.example.spring.controller;
​
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
​
/**
 * 你好控制器
 *
 * @author 爪哇小白2021
 * @date 2022/06/30
 */
@Controller
public class HelloController {
    @GetMapping("/hello")
    public String hello() {
        return "你好 爪哇小白2021";
    }
​
    /**
     * 成功后跳转页面
     * @return
     */
    @RequestMapping("/toMain")
    public String toMain(){
        return "redirect:/main.html";
    }
}

页面展示

p1

image.png p2 登录之后跳转

image.png

ps: WebSecurityConfigurerAdapter目前已经是弃用,但是仍然配置有效。

新的实现方式大抵如下

image.png