##以前做毕设的时候使用过SpringSecurity,那个时候还理解得不是很多。这次重新使用SpringSecurity有了新的理解,记录一下。
1.怎么能做到自定义登录界面
这个真的很坑,上网找了很多资料。找到有说要在src/main/resources下再建一个/resources文件夹,然后将login.html放到里面去。
这个login.html可以换名字,换了的名字要在SecurityConfiguration里写上.
loginProcessingUrl是对应表单提交的路径,要跟html上一致
loginPage则是对应自己的登录界面。
2.怎么做到基于数据库的权限控制与登录
这个问题我在网上一直搜不到,最后算是一边看一边学摸索出来了。
首先你要有一个自己的Service验证,要继承UserDetailsService。然后重写loadUserByUsername方法。代码如下:
package com.example.demo.Service.SercurityConfig;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import com.example.demo.Service.People.ShipperService;
import com.example.demo.entity.People.shipper;
@Service
public class MyUserService implements UserDetailsService {
private static Logger logger =LoggerFactory.getLogger(UserDetailsService.class);
private static BCryptPasswordEncoder bc;
@Autowired
private ShipperService shipperService;
private BCryptPasswordEncoder getPasswordEncoder() {
if(this.bc==null) {
this.bc=new BCryptPasswordEncoder();
}
return this.bc;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
// TODO Auto-generated method stub
logger.info("MyUserService---loadUserByUsername:"+username);
UserDetails user=null;
List<shipper> selectByName = shipperService.selectByName(username);
if(selectByName.size()!=0) {
shipper shipper = selectByName.get(0);
logger.info(shipper.toString());
Collection<GrantedAuthority> authorities = getAuthorities(shipper);
user=new User(username,shipper.getShipperPassword(),true,true,true,true,authorities);
}
return user;
}
private Collection<GrantedAuthority> getAuthorities(shipper shipper){
List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();
authList.add(new SimpleGrantedAuthority("ROLE_"+"ADMIN"));
return authList;
}
}
说明一下:在loadUserByUsername方法会拿到用户输入的username,你需要通过username从数据库查用户信息,然后将用户名,密码等属性装填到UserDetails里,返回给Security。它会自己验证密码等。在这一步,你可以加载用户的权限。我的getAuthorities方法为了方便,还没有从数据库取权限字段,是直接加了ADMIN权限.这一步可以换成从数据库取.
3.自定义登录失败跳转与成功跳转
/loginFa是失败的跳转,/ttttt是成功的跳转
4.前端界面的权限控制,通过springsecurity标签
我的pom.xml
<?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.2.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>WMS-System</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>WMS-System</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<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.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId>
<version>5.7.1</version>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
前端页面:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<head>
</head>
<body>
<div class="starter-template">
<h1 th:text="${msg}"></h1>
<p class="bg-primary" th:text="${msg}"></p>
<div sec:authorize="hasRole('ROLE_ADMIN')">
<p class="bg-info" th:text="${msg}">dddd</p>
</div>
<div sec:authorize="hasRole('ROLE_ADMIN')">
<p class="bg-info">无更多显示信息</p>
</div>
<form th:action="@{/logout}" method="post">
<input type="submit" class="btn btn-primary" value="注销"/>
</form>
</div>
</body>
</html>
我的controller:
不能直接通过resources文件夹下的HTML跳转,需要通过controller跳转才可以实现
4.静态资源因为SpringSecurity加载不出来的问题
正常的静态资源要在前端加载只需要在SecurityConfiguration上声明
@Override
public void configure(WebSecurity web) throws Exception {
// TODO Auto-generated method stub
//super.configure(web);
web.ignoring().antMatchers("/css/**","/fonts/**","/images/**","/js/**");
}
然后将静态资源直接放到static文件夹下,如下:
今天我发现一个问题,如果是通过controller的GetMapping跳转的话,你要是有二级匹配路径的话,是匹配不到的。
我的html:
静态资源是这样写的。如果你像我是二级路径GetMapping的话,是找不到静态资源的。
解决方法:
静态资源前面加上"../":如下: