文章目录
1 SpringSecurity
1.2 第一个 SpringSecurity 项目
1.2.1 导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
1.2.2 访问页面
导入 spring-boot-starter-security 启动器后,Spring Security 已经生效,默认拦截全部请求,如果用户
没有登录,访问http://localhost:8080,会主动跳转到内置的登录页面。
在 SecurityProperties 中初始化了用户名和密码
/**
* Default user name.
*/
private String name = "user";
/**
* Password for the default user name.
*/
private String password = UUID.randomUUID().toString();
1.2.3 UserDetailsService
通过自定义 UserDetailsService 接口的实现类控制认证逻辑
package com.cl.mapper;
import com.cl.pojo.User;
import org.apache.ibatis.annotations.Select;
/**
* @Author chenlan
* @Description TODO
* @Date 2020/12/29 11:15
* @Version 1.0
*/
public interface UserMapper {
/**
* 根据用户名查询用户
*
* @param username
* @return
*/
@Select("select * from sys_user where username = #{username}")
User selectUserByUsername(String username);
}
package com.cl.service.impl;
import com.cl.mapper.UserMapper;
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.stereotype.Service;
import java.util.ArrayList;
/**
* @Author chenlan
* @Description TODO
* @Date 2020/12/29 10:43
* @Version 1.0
*/
@Service
public class LoginServiceImpl implements UserDetailsService {
@Autowired
private UserMapper userMapper;
/**
* @param username 用户提交的用户名
* @return UserDetails(Interface) 返回其实现类 org.springframework.security.core.userdetails.User
* @throws UsernameNotFoundException 通过用户名没有查询到相关用户则抛出异常
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// 查询当前登录用户是否存在
com.cl.pojo.User user = userMapper.selectUserByUsername(username);
if (user != null) {
/**
* org.springframework.security.core.userdetails.User
* 自定义登录逻辑时 SpringSecurity 要求 容器中必须要有 passwordEncoder 实例 用作密码验证
* User user = new User(username,password,authorities)
* @username 用户提交的用户名
* @password 数据库中查询得到的密码
* @authorities 用户具备的权限 不允许为空
*/
return new User(username, user.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("没有权限"));
}
throw new UsernameNotFoundException("用户不存在");
}
}
1.2.4 PasswordEncoder
SpringSecurity 要求容器中必须有 PasswordEncoder 实例。所以当自定义登录逻辑时要求必须
给容器注入 PaswordEncoder 的 bean 对象
1.2.4.1 自定义实例
package com.cl.util;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
/**
* @Author chenlan
* @Description TODO
* @Date 2020/12/29 10:58
* @Version 1.0
*
* 配置自定义密码编码器
*/
@Component
public class MyPasswordEncoder implements PasswordEncoder{
/**
* 设置密码加密
*
* @param rawPassword 用户提交的密码
* @return 返回加密后的密码
*/
@Override
public String encode(CharSequence rawPassword) {
return rawPassword + "cl";
}
/**
* 进行密码验证
*
* @param rawPassword 用户提交的密码(未加密)
* @param encodedPassword 查询得到的数据库密码
* @return 返回 true 则验证通过 false 则验证失败
*/
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return encode(rawPassword).equals(encodedPassword);
}
}
1.2.4.2 使用内置解析器
BCryptPasswordEncoder 是 SpringSecurity 官方推荐的密码解析器。
BCryptPasswordEncoder 是对bcrypt强散列方法的具体实现。是基于Hash算法实现的单向加
密。可以通过 strength 控制加密强度,默认10。
package com.cl.config;
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 chenlan
* @Description TODO
* @Date 2020/12/29 11:22
* @Version 1.0
*
*
* SpringSecurity 配置文件
*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 配置密码解析器
*
* @return
*/
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder(4);
}
}
1.2.5 自定义登录页面
1.2.5.1 编写登录页面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login" method="post">
<p><input type="text" name="username"/></p>
<p><input type="password" name="password"/></p>
<p><input type="submit" value="登录"/></p>
</form>
</body>
</html>
1.2.5.2 编写配置类
package com.cl.config;
import com.cl.config.handler.MyAuthenticationFailureHandler;
import com.cl.config.handler.MyAuthenticationSuccessHandler;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* @Author chenlan
* @Description TODO
* @Date 2020/12/29 11:22
* @Version 1.0
*
*
* SpringSecurity 配置文件
*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 登录配置 认证和授权
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
// 配置认证
http.formLogin()
// 配置登录成功后 跳转的 action
.successForwardUrl("/index"
// 设置登录的请求路径(登录表单的请求路径)
.loginProcessingUrl("/login")
// 配置登录失败跳转路径
.failureForwardUrl("/fail")
// 配置登录表单对应的用户名和密码
.usernameParameter("username")
.passwordParameter("password")
// 设置登录页面
.loginPage("/");
// 配置授权 (从上到下)
http.authorizeRequests()
// 设置 "login.html" 路径可以匿名访问
.antMatchers("/").anonymous()
// 配置所有请求都要进行认证
// anyRequest 等同于 antMatchers("/**")
.anyRequest().authenticated();
// 关闭 csrf 保护
http.csrf().disable();
}
/**
* 配置密码解析器
*
* @return
*/
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder(4);
}
}
1.2.5.3 编写控制层
package com.cl.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @Author chenlan
* @Description TODO
* @Date 2020/12/29 14:30
* @Version 1.0
*/
@Controller
public class UserController {
@RequestMapping("/")
public String login(){
return "login";
}
@RequestMapping("/index")
public String index(){
return "index";
}
@RequestMapping("/fail")
public String fail(){
return "fail";
}
}
1.2.6 认证其他配置
1.2.6.1 配置请求中的参数名
当进行登录时会执行 UsernamePasswordAuthenticationFilter 过滤器
在登录配置中进行配置即可
1.2.6.2 自定义登录成功处理器
在登录配置中使用 successForwardUrl() 配置登录成功时