目录
Spring Security 的前身是 Acegi Security ,是 Spring 项目组中用来提供安全认证服务的框架。
(Spring Security) Spring Security 为基于J2EE企业应用软件提供了全面安全服务。特别是使用领先的J2EE解决方案-Spring框架开发的企业软件项目。人们使用Spring Security有很多种原因,不过通常吸引他们的是在J2EE Servlet规范或EJB规范中找不到典型企业应用场景的解决方案。特别要指出的是他们不能再WAR 或 EAR 级别进行移植。这样,如果你更换服务器环境,就要,在新的目标环境进行大量的工作,对你的应用系统进行重新配置安全。使用Spring Security 解决了这些问题,也为你提供很多有用的,完全可以指定的其他安全特性。安全包括两个主要操作:认证和授权。
认证,是为用户建立一个他所声明的主体。主题一般式指用户,设备或可以在你系统中执行动作的其他系统。(简单来说:系统认为用户是否能登录)
授权指的是一个用户能否在你的应用中执行某个操作,在到达授权判断之前,身份的主题已经由身份验证过程建立了。(简单来说:系统判断用户是否有权限去做某些事情)
这些概念是通用的,不是Spring Security特有的。在身份验证层面,Spring Security广泛支持各种身份验证模式,这些验证模型绝大多数都由第三方提供,或则正在开发的有关标准机构提供的,例如 Internet Engineering TaskForce作为补充,Spring Security 也提供了自己的一套验证功能。

- "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.0modelVersion>
-
- <groupId>cn.itssl.springmvcgroupId>
- <artifactId>springmvc_springsecurityartifactId>
- <version>1.0-SNAPSHOTversion>
- <packaging>warpackaging>
-
- <properties>
- <spring.version>5.2.9.RELEASEspring.version>
- <spring.security.version>5.2.9.RELEASEspring.security.version>
- properties>
- <dependencies>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-coreartifactId>
- <version>${spring.version}version>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-webartifactId>
- <version>${spring.version}version>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-webmvcartifactId>
- <version>${spring.version}version>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-context-supportartifactId>
- <version>${spring.version}version>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-testartifactId>
- <version>${spring.version}version>
- dependency>
- <dependency>
- <groupId>org.springframeworkgroupId>
- <artifactId>spring-jdbcartifactId>
- <version>${spring.version}version>
- dependency>
-
- <dependency>
- <groupId>org.springframework.securitygroupId>
- <artifactId>spring-security-webartifactId>
- <version>${spring.security.version}version>
- dependency>
- <dependency>
- <groupId>org.springframework.securitygroupId>
- <artifactId>spring-security-configartifactId>
- <version>${spring.security.version}version>
- dependency>
- <dependency>
- <groupId>javax.servletgroupId>
- <artifactId>javax.servlet-apiartifactId>
- <version>3.1.0version>
- <scope>providedscope>
- dependency>
- dependencies>
-
-
- project>
web.xml
- "1.0" encoding="UTF-8"?>
- <web-app xmlns="http://java.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
- http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
- version="3.0">
- <context-param>
-
- <param-name>contextConfigLocationparam-name>
- <param-value>classpath:spring-security.xmlparam-value>
- context-param>
- <listener>
-
- <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class>
- listener>
-
- <filter>
- <filter-name>springSecurityFilterChainfilter-name>
- <filter-class>org.springframework.web.filter.DelegatingFilterProxyfilter-class>
- filter>
- <filter-mapping>
- <filter-name>springSecurityFilterChainfilter-name>
- <url-pattern>/*url-pattern>
- filter-mapping>
- web-app>
spring-security.xml
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:security="http://www.springframework.org/schema/security"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd">
-
- <security:http auto-config="true" use-expressions="false">
-
- <security:intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN"/>
-
-
- security:http>
-
- <security:authentication-manager>
- <security:authentication-provider>
- <security:user-service>
-
-
- <security:user name="user" password="{noop}user"
- authorities="ROLE_USER" />
- <security:user name="admin" password="{noop}admin"
- authorities="ROLE_ADMIN" />
- security:user-service>
- security:authentication-provider>
- security:authentication-manager>
- beans>
启动tomcat,可以发现我们并没有写任何页面,为什么会出现一个登录页面呢?这是因为springSecurity安全框架底层为我们提供的页面,并且我们可以通过这个页面去登录,在spring-security配置文件中我们配置了两个账号,一个是user,一个是admin,我们就可以在页面进行登录验证。

输入user或admin其中一个,进行登录验证

登录成功,注意:这里的Hello World页面并不是我们本地的index.jsp页面,也是安全框架为我们写好的成功页面

以上我们进行了一个简单的快速入门,不过是安全框架自带的登录,那我们以后做自己的项目,如何用安全框架呢?
login.html页面,需要特别注意的是:这里面的username和password填入框的name属性必须为username和password,因为安全框架后台去接收的时候会根据这两个名字,如果不是这两个名字,则接收不到。
login页面根据自己的项目编写,这里我就不提供了。
配置spring-security配置文件
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:security="http://www.springframework.org/schema/security"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd">
-
- <security:http pattern="/login.jsp" security="none"/>
- <security:http pattern="/failer.jsp" security="none"/>
- <security:http pattern="/css/**" security="none"/>
- <security:http pattern="/img/**" security="none"/>
- <security:http pattern="/plugins/**" security="none"/>
-
-
- <security:http auto-config="true" use-expressions="false">
-
- <security:intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN"/>
-
- <security:form-login login-page="/login.jsp"
- login-processing-url="/login"
- authentication-failure-url="/failer.jsp"
- default-target-url="/index.jsp"
- authentication-success-forward-url="/pages/main.jsp"/>
-
- <security:csrf disabled="true" />
-
- <security:logout invalidate-session="true" logout-url="/logout" logout-success-url="/login.jsp" />
-
- security:http>
-
- <security:authentication-manager>
-
- <security:authentication-provider user-service-ref="userService">
-
- security:authentication-provider>
- security:authentication-manager>
-
-
- beans>
web.xml文件与之前的一样,不用改变。
UserInfo类
- @Data
- public class UserInfo {
- private String id;
- private String username;
- private String email;
- private String password;
- private String phoneNum;
- private int status;
- private String statusStr;
- private List
roles; -
-
- public String getStatusStr() {
- if (this.status == 1) {
- return this.statusStr = "开启";
- }
- if (this.status == 0) {
- return this.statusStr = "禁用";
- }
- return this.statusStr = " ";
- }
- }
Role类
- @Data
- public class Role {
- private String id;
- private String roleName;
- private String roleDesc;
- private List
permissions; - private List
users; - }
users
- CREATE TABLE `users` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `email` varchar(50) NOT NULL,
- `username` varchar(255) DEFAULT NULL,
- `password` varchar(255) DEFAULT NULL,
- `phoneNum` varchar(20) DEFAULT NULL,
- `status` int(11) DEFAULT NULL COMMENT '状态0 未开启 1 开启',
- PRIMARY KEY (`id`) USING BTREE
- ) ENGINE=InnoDB AUTO_INCREMENT=20629 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
role
- CREATE TABLE `role` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `roleName` varchar(255) DEFAULT NULL,
- `roleDesc` varchar(255) DEFAULT NULL,
- PRIMARY KEY (`id`) USING BTREE
- ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
继承UserDetailsService接口,这个接口就是安全框架为我们提供的
- public interface UserService extends UserDetailsService {
-
-
- }
创建实现类,实现UserService类,重写UserService接口继承的UserDetailsService接口下的方法loadUserByUsername
- @Service("userService")
- public class UserServiceImpl implements UserService {
- @Autowired
- private UserMapper userMapper;
-
- /**
- * @description:查询用户
- * @param: [s]
- * @return: org.springframework.security.core.userdetails.UserDetails
- **/
- @Override
- public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
- UserInfo userInfo = userMapper.findUserByUserName(s);
- User user = new User(
- userInfo.getUsername(),//用户账号
- "{noop}"+userInfo.getPassword(),//用户密码 使用明文
- userInfo.getStatus()==0?false:true,//校验用户是否开启
- true,//账号是否过期 不过期
- true,//账号 不过期
- true,//账号 不锁定
- getAuthority(userInfo.getRoles()));
- return user;
- }
-
- /**
- * @description:查询用户的角色
- * @param: []
- * @return: java.util.List
- **/
- private List
getAuthority(List roles) { - List
list = new ArrayList<>(); - for (Role role : roles) {
- list.add(new SimpleGrantedAuthority("ROLE_"+role.getRoleName()));
- }
- return list;
- }
-
- }
- public interface UserMapper {
- /**
- * @description:查询用户
- * @param: [s]
- * @return: cn.itssl.pojo.UserInfo
- **/
- UserInfo findUserByUserName(String s);
- }
- public interface UserMapper {
- /**
- * @description:查询用户
- * @param: [s]
- * @return: cn.itssl.pojo.UserInfo
- **/
- UserInfo findUserByUserName(String s);
-
- }
- "1.0" encoding="UTF-8" ?>
- mapper
- PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
- "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- <mapper namespace="cn.itssl.mapper.UserMapper">
- <resultMap id="findUserResult" type="UserInfo" autoMapping="true">
- <id property="id" column="id"/>
- <collection property="roles" javaType="List" ofType="Role" autoMapping="true">
- <id property="id" column="id"/>
- collection>
- resultMap>
- <select id="findUserByUserName" resultMap="findUserResult">
- select *
- from users u,
- role r,
- users_role ur
- where
- u.id = ur.userId
- and
- r.id = ur.roleId
- and
- username = #{s};
- select>
- mapper>
启动tomcat以后,会自动进入login.jsp页面

输入正确的用户和密码,则就进入了后台系统。
输入用户密码错误的话,则报错提示

导入jsr250注解的依赖
- <dependency>
- <groupId>javax.annotationgroupId>
- <artifactId>jsr250-apiartifactId>
- <version>1.0version>
- dependency>
在springmvc-config.xml配置文件中开启jsr250注解
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:security="http://www.springframework.org/schema/security"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
-
- <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <property name="prefix" value="/pages/"/>
- <property name="suffix" value=".jsp"/>
- bean>
-
- <mvc:annotation-driven/>
-
- <context:component-scan base-package="cn.itssl.*"/>
-
- <mvc:default-servlet-handler/>
-
- <mvc:annotation-driven>
- <mvc:message-converters>
- <bean class="org.springframework.http.converter.StringHttpMessageConverter">
- <property name="supportedMediaTypes">
- <list>
- <value>text/html;charset=utf-8value>
- list>
- property>
- bean>
- mvc:message-converters>
- mvc:annotation-driven>
-
-
-
- <security:global-method-security jsr250-annotations="enabled"/>
-
- beans>
| 注解 | 说明 |
|---|---|
| @RolesAllowed | 表示访问对应方法时所应该具有的角色 |
| @PermitAll | 表示允许所有的角色进行访问,也就是说不进行权限控制 |
| @DenyAll | 和PermitAll相反的,表示无论什么角色都不能访问 |
在controller层进行添加注解
- /**
- * 查询所有用户
- */
- @RolesAllowed("ADMIN")
- @RequestMapping("findAll")
- public ModelAndView findAll(
- @RequestParam(name="page",defaultValue = "1")Integer page,
- @RequestParam(name="size",defaultValue = "5")Integer size) {
- ModelAndView mv = new ModelAndView();
- List
userList = userService.findAllUsers(page,size); - PageInfo pageInfo=new PageInfo(userList);
- mv.addObject("pageInfo", pageInfo);
- mv.setViewName("user-list");
- return mv;
- }
@RolesAllowed("ADMIN") 在方法上findAll(查询所有用户)使用代表的是只有ADMIN的权限才能访问该功能
使用其他用户进行登录,其他用户没有ADMIN和USER权限,再进行访问 findProductByParams该方法时,会报403错误

开启@Secured注解
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:security="http://www.springframework.org/schema/security"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
-
- <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <property name="prefix" value="/pages/"/>
- <property name="suffix" value=".jsp"/>
- bean>
-
- <mvc:annotation-driven/>
-
- <context:component-scan base-package="cn.itssl.*"/>
-
- <mvc:default-servlet-handler/>
-
- <mvc:annotation-driven>
- <mvc:message-converters>
- <bean class="org.springframework.http.converter.StringHttpMessageConverter">
- <property name="supportedMediaTypes">
- <list>
- <value>text/html;charset=utf-8value>
- list>
- property>
- bean>
- mvc:message-converters>
- mvc:annotation-driven>
-
-
-
-
- <security:global-method-security jsr250-annotations="enabled" secured-annotations="enabled"
- pre-post-annotations="enabled"/>
-
-
- beans>
@Secured注解标注的方法进行权限控制的支持,其值默认为disabled。
- /**
- * 查询所有用户
- */
- @Secured("ROLE_ADMIN")//只有admin才可以访问
- @RequestMapping("findAll")
- public ModelAndView findAll(
- @RequestParam(name="page",defaultValue = "1")Integer page,
- @RequestParam(name="size",defaultValue = "5")Integer size) {
- ModelAndView mv = new ModelAndView();
- List
userList = userService.findAllUsers(page,size); - PageInfo pageInfo=new PageInfo(userList);
- mv.addObject("pageInfo", pageInfo);
- mv.setViewName("user-list");
- return mv;
- }
- "1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:security="http://www.springframework.org/schema/security"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
-
- <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
- <property name="prefix" value="/pages/"/>
- <property name="suffix" value=".jsp"/>
- bean>
-
- <mvc:annotation-driven/>
-
- <context:component-scan base-package="cn.itssl.*"/>
-
- <mvc:default-servlet-handler/>
-
- <mvc:annotation-driven>
- <mvc:message-converters>
- <bean class="org.springframework.http.converter.StringHttpMessageConverter">
- <property name="supportedMediaTypes">
- <list>
- <value>text/html;charset=utf-8value>
- list>
- property>
- bean>
- mvc:message-converters>
- mvc:annotation-driven>
-
-
-
-
-
- <security:global-method-security jsr250-annotations="enabled" secured-annotations="enabled"
- pre-post-annotations="enabled"/>
-
- beans>
| 注解 | 说明 |
|---|---|
| @PreAuthorize | 在方法调用之前,基于表达式的计算结果来限制对方法的访问 |
| @PostAuthorize | 在方法调用之后,允许方法调用,但是如果表达式计算结果为false,将抛出一个安全性异常 |
| @PostFilter | 允许方法调用,但必须按照表达式来过滤方法的结果--了解 |
| @PreFilter | 允许方法调用,但必须在进入方法之前过滤输入值--了解 |
- /**
- * 查询所有用户
- */
- @PreAuthorize("authentication.principal.username == 'itssl'")//只有itssl才可以访问
- @RequestMapping("findAll")
- public ModelAndView findAll(
- @RequestParam(name="page",defaultValue = "1")Integer page,
- @RequestParam(name="size",defaultValue = "5")Integer size) {
- ModelAndView mv = new ModelAndView();
- List
userList = userService.findAllUsers(page,size); - PageInfo pageInfo=new PageInfo(userList);
- mv.addObject("pageInfo", pageInfo);
- mv.setViewName("user-list");
- return mv;
- }
-
- /**
- * 新增用户
- */
- @PreAuthorize("hasRole('ROLE_USER')") // 只有【ROLE_USER】该权限才能访问该方法
- @RequestMapping("save")
- public String save(UserInfo userInfo){
- userService.save(userInfo);
- return "redirect:findAll.do";
- }
在jsp页面中我们可以使用spring security提供的权限标签来进行权限控制
- <dependency>
- <groupId>org.springframework.securitygroupId>
- <artifactId>spring-security-taglibsartifactId>
- <version>5.2.9.RELEASEversion>
- dependency>
<%@taglib uri="http://www.springframework.org/security/tags" prefix="security"%>
在jsp中我们可以使用以下三种标签,其中authentication代表的是当前认证对象,可以获取当前认证对象信息,例如用户名。其它两个标签我们可以用于权限控制。
authentication标签
<security:authentication property="" htmlEscape="" scope="" var=""/>
property: 只允许指定Authentication所拥有的属性,可以进行属性的级联获取,如“principle.username”,不允许直接通过方法进行调用
htmlEscape:表示是否需要将html进行转义。默认为true。
scope:与var属性一起使用,用于指定存放获取的结果的属性名的作用范围,默认我pageContext。Jsp中拥有的作用范围都进行进行指定
var: 用于指定一个属性名,这样当获取到了authentication的相关信息后会将其以var指定的属性名进行存放,默认是存放在pageConext中
authorize标签
authorize是用来判断普通权限的,通过判断用户是否具有对应的权限而控制其所包含内容的显示
<security:authorize access="" method="" url="" var="">security:authorize>
access: 需要使用表达式来判断权限,当表达式的返回结果为true时表示拥有对应的权限
method:method属性是配合url属性一起使用的,表示用户应当具有指定url指定method访问的权限,
method的默认值为GET,可选值为http请求的7种方法
url:url表示如果用户拥有访问指定url的权限即表示可以显示authorize标签包含的内容
var:用于指定将权限鉴定的结果存放在pageContext的哪个属性中
<security:authentication property="principal.username">security:authentication>
需要在spring-security配置文件中注入以下bean
<bean id="webSecurityExpressionHandler" class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler"/>
代表只有ADMIN权限的用户才显示该功能 (只有登录的用户拥有ADMIN角色才可以看到以下页面)
- <li id="system-setting1">
- <security:authorize access="hasRole('ADMIN')">
- <a href="${pageContext.request.contextPath}/user/findAll.do?page=1&size=5">
- <span class="glyphicon glyphicon-object-align-bottom">span> 用户管理
- a>
- security:authorize>
- li>
- <li id="system-setting2">
- <security:authorize access="hasRole('ADMIN')">
- <a href="${pageContext.request.contextPath}/role/findAll.do?page=1&size=5">
- <span class="glyphicon glyphicon-object-align-bottom">span> 角色管理
- a>
- security:authorize>
- li>
- <li id="system-setting3">
- <security:authorize access="hasRole('ADMIN')">
- <a href="${pageContext.request.contextPath}/permission/findAll.do?page=1&size=5">
- <span class="glyphicon glyphicon-object-align-bottom">span> 资源权限管理
- a>
- security:authorize>
- li>
- <li id="system-setting4">
- <security:authorize access="hasRole('ADMIN')">
- <a href="${pageContext.request.contextPath}/sysLog/findAll.do?page=1&size=5">
- <span class="glyphicon glyphicon-object-align-bottom">span> 访问日志
- a>
- security:authorize>
- li>