1、 新建SpringBoot项目,依赖为thymeleaf-extras-springsecurity5、spring-boot-start-thymeleaf、mybatis-spring-boot-start
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.security</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--添加mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.23</version>
</dependency>
<!--添加thymeleaf对security的支持-->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<!--集成security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2、 定义用户类继承UserDetails:
package com.security.demo.Entity;
public class SysUser implements UserDetails {
private int id;
private String username;
private String password;
private String roles;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
//注意使用IDEA直接生成实现方法时下面四个方法会默认返回false,需要将其改为true
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public void setUsername(String username) {
this.username = username;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> authorities = new ArrayList<>();
String roles = this.getRoles();
//将用户角色作为权限
authorities.add(new SimpleGrantedAuthority(roles));
System.out.println("authors:"+authorities.get(0).toString());;
return authorities;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRoles() {
return roles;
}
public void setRoles(String roles) {
this.roles = roles;
}
public SysUser(int id, String username, String password, String roles) {
this.id = id;
this.username = username;
this.password = password;
this.roles = roles;
}
public SysUser() {
}
@Override
public String toString() {
return "SysUser{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", roles=" + roles +
'}';
}
}
3、角色类:
package com.security.demo.Entity;
public class SysRole {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public SysRole(int id, String name) {
this.id = id;
this.name = name;
}
}
4、MyBatis查询DAO层接口:
package com.security.demo.DAO;
@Mapper
@Repository
public interface SysUserDAO {
@Select("SELECT U.id id,U.username username, U.password password,R.name roles\n" +
"FROM SYS_USER AS U,SYS_ROLE AS R,SYS_USER_ROLES AS UR\n" +
"WHERE U.username = #{username} and UR.sys_user_id = U.id and R.id = UR.roles_id")
SysUser findByUsername(String username);
}
5、ConstomUserService实现UserDetailsService,重写loadUserByUsername方法获得用户:
package com.security.demo.ServiceImpl;
public class ConstomUserService implements UserDetailsService {
@Autowired
SysUserDAO sysUserDAO;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
SysUser user = sysUserDAO.findByUsername(s);
if (user == null){
throw new UsernameNotFoundException("用户名不存在");
}
return user;
}
}
6、SpringMVC配置:
package com.security.demo.Configuration;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
}
7、Spring Security配置:
package com.security.demo.Configuration;
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
UserDetailsService customService(){//注册CustomUserService的Bean
return new ConstomUserService();
}
@Bean
public static NoOpPasswordEncoder passwordEncoder() {//Spring官方已经不推荐使用这个方法了
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customService());;//添加我们自定义的user Detail service认证
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated()//所有请求登录后才能访问
.and()
.formLogin().loginPage("/login").failureUrl("/login?error").permitAll().//定制登录行为,登录页面可以任意访问
and().logout().permitAll();//定制注销行为,注销请求可以任意访问
}
}
8、登录界面:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<form th:action="@{/login}" action="/login" method="post">
<input type="text" name="username" placeholder="账号">
<input placeholder="密码" type="password" name="password">
<input type="submit" id="login" th:value="Login">
</form>
</body>
</html>
9、首页:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1 th:text="${msg.title}"></h1>
<div sec:authorize="hasRole('ROLE_ADMIN')">
<p th:text="${msg.etraInfo}"></p>
</div>
<div sec:authorize ="hasRole('ROLE_USER')">
<p>无更多信息显示</p>
</div>
</body>
</html>
10、项目结构:
11、运行结果:
(1)访问localhost:8080
(2)管理员登录后:
(3)用户登录后:
11、控制类:
package com.security.demo.Controller;
@Controller
public class HomeController {
@RequestMapping("/")
public String index(Model model){
Msg msg = new Msg("测试标题","测试内容","额外信息,只对管理员显示");//此处Msg为自定义的一个实体类,主要用于传输信息
model.addAttribute("msg",msg);
return "home";
}
}
综上,要实现Sercurity用户验证,
(1)创建一个用户类SysUser extends UserDetails 实现UserDetails中的方法,创建角色类,重写getAuthorits(),将用户角色作为权限
(2)自定义类实现UserDetailsService接口,重写loadByUsername()方法,将从数据库中查出的SysUser返回给Spring Security使用
(3)配置Spring Security,配置类WebSecurityConfig extends WebSecurityConfigurerAdapter,重写config(AuthenticationManagerBuilder auth)方法,添加我们自定义的user details service认证,然后重写configer(HttpSecurity http)方法