Spring Security是Spring采用 AOP
思想,基于 servlet过滤器
实现的安全框架。它提供了完善的认证机制和方法级的授权功能。是一款非常优秀的权限管理框架。
特征
准备一个SpringMVC+Spring+jsp的Web环境,然后在这个基础上整合SpringSecurity。
添加相关的依赖
junit
junit
4.11
test
org.springframework
spring-webmvc
5.2.1.RELEASE
javax.servlet
servlet-api
2.5
provided
org.slf4j
slf4j-log4j12
1.7.25
log4j.properties文件
log4j.rootCategory=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n
web.xml
Archetype Created Web Application
contextConfigLocation
classpath:applicationContext.xml
org.springframework.web.context.ContextLoaderListener
CharacterEncodingFilter
org.springframework.web.filter.CharacterEncodingFilter
encoding
utf-8
CharacterEncodingFilter
/*
dispatcherServletb
org.springframework.web.servlet.DispatcherServlet
contextConfigLocation
classpath:spring-mvc.xml
1
dispatcherServletb
/
添加Tomcat的插件 启动测试
org.apache.tomcat.maven
tomcat7-maven-plugin
2.2
8082
/
添加相关的依赖
spring-security-core.jar 核心包,任何SpringSecurity的功能都需要此包
spring-security-web.jar:web工程必备,包含过滤器和相关的web安全的基础结构代码
spring-security-config.jar:用于xml文件解析处理
spring-security-tablibs.jar:动态标签库
org.springframework.security
spring-security-config
5.1.5.RELEASE
org.springframework.security
spring-security-taglibs
5.1.5.RELEASE
web.xml文件中配置SpringSecurity
springSecurityFilterChain
org.springframework.web.filter.DelegatingFilterProxy
springSecurityFilterChain
/*
添加SpringSecurity的配置文件
将SpringSecurity的配置文件引入到Spring配置文件中
启动测试访问
如何使用我们自己写的登录页面呢?
<%--
Created by IntelliJ IDEA.
User: dpb
Date: 2021/3/16
Time: 16:57
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
Title
登录页面
修改相关的配置文件
访问home.jsp页面后会自动跳转到自定义的登录页面
但是当提交了请求后页面出现了如下的错误
为什么系统默认的登录页面提交没有CRSF拦截的问题呢
自定义的认证页面没有这个信息怎么办呢?两种方式:
前面的案例账号信息是直接写在配置文件中的,这显然是不太好的,如何实现和数据库中的信息进行认证?
添加相关的依赖
org.mybatis
mybatis
3.5.4
org.mybatis
mybatis-spring
2.0.4
mysql
mysql-connector-java
8.0.11
com.alibaba
druid
1.1.8
添加配置文件
jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/logistics?characterEncoding=utf-8&serverTimezone=UTC
jdbc.username=root
jdbc.password=123456
需要完成认证的service中继承 UserDetailsService父接口
实现类中实现验证方法
@Service
public class UserServiceImpl extends UserDetailsService {
@Autowired
private UserMapper mapper;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
// 根据账号查询用户信息
UserExample example = new UserExample();
example.createCriteria().andUserNameEqualTo(s);
List<User> users = mapper.selectByExample(example);
if(users != null && users.size() > 0){
User user = users.get(0);
if(user != null){
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
// 设置登录账号的角色
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
UserDetails userDetails = new org.springframework.security.core.userdetails.User(
user.getUserName(),"{noop}"+user.getPassword(),authorities
);
return userDetails;
}
}
return null;
}
}
最后修改配置文件关联自定义的service即可
在SpringSecurity中推荐我们是使用的加密算法是 BCryptPasswordEncoder
修改配置文件
用户的状态包括 是否可用,账号过期,凭证过期,账号锁定等等。
可以在用户的表结构中添加相关的字段来维护这种关系
在表单页面添加一个 记住我
的按钮.
在SpringSecurity中默认是关闭 RememberMe功能的,需要放开
记住我的功能会方便大家的使用,但是安全性却是令人担忧的,因为Cookie信息存储在客户端很容易被盗取,这时我们可以将这些数据持久化到数据库中。
CREATE TABLE `persistent_logins` (
`username` VARCHAR (64) NOT NULL,
`series` VARCHAR (64) NOT NULL,
`token` VARCHAR (64) NOT NULL,
`last_used` TIMESTAMP NOT NULL,
PRIMARY KEY (`series`)
) ENGINE = INNODB DEFAULT CHARSET = utf8
注意设置了过期时间,到期后并不是删除表结构中的数据,而是客户端不会在携带相关信息了,同时删除掉数据库中的数据 记住我
也会失效
开启注解的支持
jsr250的使用
添加依赖
javax.annotation
jsr250-api
1.0
控制器中通过注解设置
@Controller
@RequestMapping("/user")
public class UserController {
@RolesAllowed(value = {"ROLE_ADMIN"})
@RequestMapping("/query")
public String query(){
System.out.println("用户查询....");
return "/home.jsp";
}
@RolesAllowed(value = {"ROLE_USER"})
@RequestMapping("/save")
public String save(){
System.out.println("用户添加....");
return "/home.jsp";
}
@RequestMapping("/update")
public String update(){
System.out.println("用户更新....");
return "/home.jsp";
}
}
Spring表达式的使用
@Controller
@RequestMapping("/order")
public class OrderController {
@PreAuthorize(value = "hasAnyRole('ROLE_USER')")
@RequestMapping("/query")
public String query(){
System.out.println("用户查询....");
return "/home.jsp";
}
@PreAuthorize(value = "hasAnyRole('ROLE_ADMIN')")
@RequestMapping("/save")
public String save(){
System.out.println("用户添加....");
return "/home.jsp";
}
@RequestMapping("/update")
public String update(){
System.out.println("用户更新....");
return "/home.jsp";
}
}
SpringSecurity提供的注解
@Controller
@RequestMapping("/role")
public class RoleController {
@Secured("ROLE_USER")
@RequestMapping("/query")
public String query(){
System.out.println("用户查询....");
return "/home.jsp";
}
@Secured("ROLE_ADMIN")
@RequestMapping("/save")
public String save(){
System.out.println("用户添加....");
return "/home.jsp";
}
@RequestMapping("/update")
public String update(){
System.out.println("用户更新....");
return "/home.jsp";
}
}
异常处理
新增一个错误页面,然后在SpringSecurity的配置文件中配置即可
当然也可以使用SpringMVC中的各种异常处理器处理
注解的权限管理可以控制用户是否具有这个操作的权限,但是当用户具有了这个权限后进入到具体的操作页面,这时我们还有进行更细粒度的控制,这时注解的方式就不太适用了,这时可以通过标签来处理
添加SpringSecurity的标签库
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
Title
欢迎光临...
用户查询
用户添加
用户更新
用户删除
页面效果