绪:
通过这个查,参照别人的demo实现了security权限认证,可能有些地方写的不对,供参考!希望对你有帮助
本文参照 https://www.cnblogs.com/ealenxie/p/9293768.html
一.配置
1.pom配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
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>
<groupId>com.zhaoyu.spingbootSecurity</groupId>
<artifactId>practice1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>practice1</name>
<description>Demo project for Spring Boot and Security</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--JPA-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!--security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<!--security和thymeleaf整合的-->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity4</artifactId>
</dependency>
<!--thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--web支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--H2内存数据库-->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
</configuration>
</plugin>
</plugins>
</build>
</project>
添加了WEB、JPA、Thymeleaf、H2、SpringSecurity的pom
1.application.properties配置
server.port=80
spring.thymeleaf.mode=HTML5
spring.thymeleaf.cache=false
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
#h2
#spring.h2.console.path=/h2
#spring.h2.console.enabled=true
#spring.datasource.url=jdbc:h2:~/test4;DB_CLOSE_ON_EXIT=FALSE;AUTO_SERVER=TRUE
#spring.datasource.driver-class-name: com.mysql.jdbc.Driver
spring.datasource.url: jdbc:mysql://localhost:3306/forsecurity?useUnicode=true&characterEncoding=utf-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driverClassName=com.mysql.jdbc.Driver
二、代码部分
1.User实体实现了序列化、UserDetails、GrantedAuthority
序列化为了持久化
UserDetails为了权限开放
GrantedAuthority为了指定权限(感觉就是告诉哪个是关键字)
package com.zhaoyu.spingbootsecurity.practice1.domain;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import javax.persistence.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@Entity
public class User implements Serializable,UserDetails,GrantedAuthority {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 20)
private String username;
@Column(length = 200)
private String password;
@Column(length = 40)
private String email;
@Column(length = 20)
private String role;//权限
protected User() {
}
public User(String username, String password, String email) {
this.username = username;
this.password = password;
this.email = email;
}
public Collection<? extends GrantedAuthority> getAuthorities() {
// 需将 List<Authority> 转成 List<SimpleGrantedAuthority>,否则前端拿不到角色列表名称
List<SimpleGrantedAuthority> simpleAuthorities = new ArrayList<>();
if(this.role.contains(",")){
simpleAuthorities.add(new SimpleGrantedAuthority(this.getAuthority()));
}
String [] roles=this.getAuthority().split(",");
for (String role:roles
) {
simpleAuthorities.add(new SimpleGrantedAuthority(role));
}
return simpleAuthorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
@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 Long getId() {
return id;
}
public void setPassword(String password) {
this.password =password;
}
public void setBCryptPassword(String password) {
this.password =new BCryptPasswordEncoder(4).encode(password);
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public void setId(Long id) {
this.id = id;
}
public void setRole(String role) {
this.role = role;
}
@Override
public String getAuthority() {
return role;
}
}
2.Controller
package com.zhaoyu.spingbootsecurity.practice1.controller;
import com.zhaoyu.spingbootsecurity.practice1.domain.User;
import com.zhaoyu.spingbootsecurity.practice1.repository.UserRepository;
import com.zhaoyu.spingbootsecurity.practice1.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
@Controller
@RequestMapping("/index")
public class UserController {
@Autowired
private UserRepository userRepository;
@Autowired
private UserService userService;
@GetMapping
public String toIndex(Model model) {
List<User> users = userRepository.findAll();
model.addAttribute("users", users);
return "/index";
}
@PostMapping("/toindex")
public ModelAndView loginEnd(User user) {
User user2 = userService.login(user);
if (user2 != null) {
return new ModelAndView("redirect:/index", "loginUser", user2);
}
return new ModelAndView("login", "loginFail", "登录失败");
}
@GetMapping("delete/{id}")
public String deleteUser(@PathVariable Long id){
userRepository.deleteById(id);
return "redirect:/index";
}
@GetMapping("/{id}")
public String getUser(Model model,@PathVariable Long id) {
User user = userRepository.findById(id).get();
model.addAttribute("one", user);
return "/userInfo";
}
@PostMapping("/add")
public String addUser(User user) {
user.setBCryptPassword(user.getPassword());
userRepository.save(user);
System.out.println("保存了");
return "redirect:/index";
}
@GetMapping("/touserForm")
public String addUser() {
return "/userForm";
}
}
负责各种接口
3.repository
package com.zhaoyu.spingbootsecurity.practice1.repository;
import com.zhaoyu.spingbootsecurity.practice1.domain.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserRepository extends JpaRepository<User, Long> {
public User findUserByIdAndUsername(Long id, String name);
public User findByUsernameAndPassword(String name, String possword);
public User findByUsername(String name);
}
提供数据库操作支持
4.WebSecurityConfig配置
package com.zhaoyu.spingbootsecurity.practice1.condig;
import com.zhaoyu.spingbootsecurity.practice1.domain.User;
import com.zhaoyu.spingbootsecurity.practice1.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启security注解
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private static final Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);
@Override
protected void configure(HttpSecurity http) throws Exception { //配置策略
http.csrf().disable();
http.authorizeRequests().
antMatchers("/static/**").permitAll().anyRequest().authenticated().
and().formLogin().loginPage("/tologin").loginProcessingUrl("/login").permitAll().successHandler(loginSuccessHandler()).
and().logout().permitAll().invalidateHttpSession(true).
deleteCookies("JSESSIONID").logoutSuccessHandler(logoutSuccessHandler()).
and().sessionManagement().maximumSessions(10).expiredUrl("/tologin");
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService());//.passwordEncoder(passwordEncoder())
auth.eraseCredentials(false);
//auth.inMemoryAuthentication().withUser("123").password(new BCryptPasswordEncoder(4).encode("123")).roles("user");
// auth.inMemoryAuthentication().withUser("111").password(new BCryptPasswordEncoder(4).encode("111")).roles("admin");
}
@Bean
public BCryptPasswordEncoder passwordEncoder() { //密码加密
return new BCryptPasswordEncoder(4);
}
@Bean
public LogoutSuccessHandler logoutSuccessHandler() { //登出处理
return new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
try {
User user = (User) authentication.getPrincipal();
logger.info("USER : " + user.getUsername()+ " LOGOUT SUCCESS ! ");
} catch (Exception e) {
logger.info("LOGOUT EXCEPTION , e : " + e.getMessage());
}
httpServletResponse.sendRedirect("/tologin");
}
};
}
@Bean
public SavedRequestAwareAuthenticationSuccessHandler loginSuccessHandler() { //登入处理
return new SavedRequestAwareAuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
logger.info("USER : " + userDetails.getUsername() + " LOGIN SUCCESS ! ");
response.sendRedirect("/index");
super.onAuthenticationSuccess(request, response, authentication);
}
};
}
@Bean
public UserDetailsService userDetailsService() { //用户登录实现
return new UserDetailsService() {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User user = userRepository.findByUsername(s);
if (user == null){
throw new UsernameNotFoundException("Username " + s + " not found");
}
// Collection<SimpleGrantedAuthority> authorities = new ArrayList<SimpleGrantedAuthority>();
// authorities.add(new SimpleGrantedAuthority("user"));
return user;
}
};
}
}
5.login.html
<form th:action="@{/login}" method="post">
账号:
<input type="text" name="username"><br>
密码:
<input type="password" name="password"><br>
<input type="submit" value="提交"><br>
</form>
6.index.html(主页)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4"
>
<head>
<meta charset="UTF-8">
<title>主页</title>
<style type="text/css">
table {
margin: 50px auto;
border: solid 1px black;
width: 1200px;
}
td{
border: solid 1px black;
height: 20px;
text-align: center;
line-height: 20px;
padding: 0;
}
</style>
</head>
<script src="/static/jquery-3.3.1.min.js" th:src="@{/jquery-3.3.1.min.js}"></script>
<body>
<h3><a th:href="@{/index/touserForm}">添加</a></h3>
<h3 sec:authorize="hasRole('ROLE_ADMIN')">欢迎管理员登录</h3>
<h3 sec:authorize="hasRole('ROLE_USER')">欢迎普通人员员登录</h3>
<a th:href="@{/admin}" sec:authorize="hasRole('ROLE_ADMIN')">去管理员页面</a>
<button th:href="@{/tologin}">退出登录</button>
<div>
<table cellpadding="0" cellspacing="0">
<caption>个人信息表</caption>
<thead>
<td>id</td>
<td>账号</td>
<td>密码</td>
<td>邮箱</td>
<td>操作</td>
</thead>
<tbody>
<tr th:if="${users.size()} eq 0">
<td th:colspan="5">暂时没有用户信息</td>
</tr>
<tr th:each="user:${users}" th:object="${user}">
<td th:text="*{id}" id="id">1</td>
<td th:text="*{username}" id="username">赵宇</td>
<td th:text="*{password}" id="password">123456</td>
<td th:text="*{email}" id="email">756834111@qq.com</td>
<td><a th:href="'/index/'+*{id}">修改</a>
|
<a th:href="'/index/delete/'+*{id}">删除</a></td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
三、测试
@Test
public void getPaasword() {
String password=new BCryptPasswordEncoder(4).encode("123");
System.out.println("加密|"+password+"|");
}
由于Security开启了BCrypt加密,所以需要自己搞一个加密后的密码
我自己的数据库:
首先登陆(localhost/tologin)
假如账号错误会回到登录页
假如使用ROLE_ADMIN账号登录
页面中有一个"去管理员页面",只有在管理员登录时显示,并且也只有管理员才能跳转
四、总结
很多地方我自己都还没明白,只是自己用来记录学习,也可以给大家做参考 ,最重要的就是USer和security的配置类,需要重写security的接口方法!
假如有误,请指正!