【Spring-Security】Re02 基础认证流程
一、权限认证模拟操作:
编写Security配置类:
package cn.zeal4j.configuration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
 * @author Administrator
 * @file IntelliJ IDEA Spring-Security-Tutorial
 * @create 2020 09 27 21:55
 */
@Configuration
public class SecurityConfiguration {
    @Bean
    public PasswordEncoder getPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
}
编写认证逻辑:
package cn.zeal4j.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
/**
 * @author Administrator
 * @file IntelliJ IDEA Spring-Security-Tutorial
 * @create 2020 09 27 21:57
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 1、通过提供的用户名参数访问数据库,查询记录返回过来,如果记录不存在则抛出异常
        // username = "admin";
        if (!"admin".equals(username)) throw new UsernameNotFoundException("用户名不存在");
        // 2、查询出来的凭证是被加密了的,这里是模拟查询的密码
        String encode = passwordEncoder.encode("123456");
        // 权限不可以为空,所以需要这么一个工具方法简单实现
        return new User(username, encode, AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal"));
    }
}
重启项目,登陆测试:
用户名称是admin,密码是123456
填写的不是admin也一样报这个错误,但是控制台并没有抛出我们设置的异常
也就是说,UserDetails对象交给其他Security的方法来判断了

二、自定义登陆页面
在static目录编写自己的登陆页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style type="text/css">
        h3,p {
            text-align: center;
        }
    </style>
</head>
<body>
    <h3>custom login page</h3>
    <form method="post" action="/login.action" >
        <p>username: <input type="text" name="username"></p>
        <p>password: <input type="password" name="password"></p>
        <p><input type="submit" value="login"></p>
    </form>
</body>
</html>

在模版目录内编写main.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Main-Page</title>
</head>
<body>
    <h3>This is main page</h3>
</body>
</html>

在之前的Security配置类中增加这些配置:
package cn.zeal4j.configuration; 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.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; /** * @author Administrator * @file IntelliJ IDEA Spring-Security-Tutorial * @create 2020 09 27 21:55 */ @Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Bean public PasswordEncoder getPasswordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity.formLogin(). // 设置登陆行为方式为表单登陆 loginPage("/login.html"). // 设置登陆页面URL路径 loginProcessingUrl("/login.action"). // 设置表单提交URL路径 successForwardUrl("/main.page"); // 设置认证成功跳转URL路径 httpSecurity.authorizeRequests(). antMatchers("/login.html").permitAll(). // 登陆页面允许任意访问 anyRequest().authenticated(); // 其他请求均需要被授权访问 // CSRF攻击拦截关闭 httpSecurity.csrf().disable(); } }
因为main页面在模版目录中,所以需要一个控制器去跳转进去
package cn.zeal4j.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
 * @author Administrator
 * @file IntelliJ IDEA Spring-Security-Tutorial
 * @create 2020 09 27 22:35
 */
@Controller
public class LoginController {
    @RequestMapping("main.page")
    public String toMainPage() {
        return "main"; // 模版内的页面不允许重定向,忘了忘了
    }
}
登陆逻辑不发生变化,启动项目访问测试:
成功跳转!!!

三、自定义登陆失败页面
首先在static目录写一个登陆失败的页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Error-Page</title>
    <style type="text/css">
        h3,p {
            text-align: center;
        }
    </style>
</head>
<body>
    <h3>This is Error Page</h3>
    <p>Wrong Request, Please return to login page <a href="/login.html">click this link</a></p>
</body>
</html>

Security的失败页面跳转也是由配置Bean的方法决定的,请求方式是POST请求
所以这个登陆失败的页面跳转也需要一个控制器处理,因为这个页面不在模版之内,所以可以使用重定向
package cn.zeal4j.configuration; 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.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; /** * @author Administrator * @file IntelliJ IDEA Spring-Security-Tutorial * @create 2020 09 27 21:55 */ @Configuration public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Bean public PasswordEncoder getPasswordEncoder() { return new BCryptPasswordEncoder(); } @Override protected void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity.formLogin(). // 设置登陆行为方式为表单登陆 loginPage("/login.html"). // 设置登陆页面URL路径 loginProcessingUrl("/login.action"). // 设置表单提交URL路径 successForwardUrl("/main.page"). // 设置认证成功跳转URL路径 POST请求 failureForwardUrl("/error.page"); // 设置认证失败跳转URL路径 POST请求 httpSecurity.authorizeRequests(). antMatchers("/login.html").permitAll(). // 登陆页面允许任意访问 antMatchers("/error.html").permitAll(). // 失败跳转后重定向的页面也需要被允许访问 anyRequest().authenticated(); // 其他请求均需要被授权访问 // CSRF攻击拦截关闭 httpSecurity.csrf().disable(); } }
注意授权的请求处理,匹配的URL是重定向的地址,而不是控制器的URL。
控制器方法:
package cn.zeal4j.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; /** * @author Administrator * @file IntelliJ IDEA Spring-Security-Tutorial * @create 2020 09 27 22:35 */ @Controller public class LoginController { @RequestMapping("main.page") public String toMainPage() { return "main"; // 模版内的页面不允许重定向,忘了忘了 } @PostMapping("error.page") // 控制器不支持POST请求跳转解析, 需要控制器跳转 Resolved [org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported] public String redirectToErrorPage() { return "redirect:/error.html"; // 重定向要写/标识 区分模版解析 } }
登陆失败测试:

 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号