1. 简介

Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

官网:https://spring.io/projects/spring-security/

中文官网:https://www.w3cschool.cn/springsecurity/

2.创建一个web工程,我用的是maven创建

3.导入相关的依赖

<?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> <groupId>com.qbb.security</groupId>
<artifactId>ssm-security</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<spring.version>5.0.5.RELEASE</spring.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties> <dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

4.先在webapp先创建一个index.html首页面测试一下web环境

5.配置web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0"> <!--
1:DelegatingFilterProxy用于整合第三方框架(代理过滤器,非真正的过滤器,真正的过滤器需要在spring的配置文件)
整合Spring Security时过滤器的名称必须为springSecurityFilterChain,
否则会抛出NoSuchBeanDefinitionException异常
-->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <!-- 2:springmvc的核心控制器-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-security.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<!--这里根据习惯配置-->
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>

注意:web.xml里面配置的权限相关的过滤器,名字不能改(必须为springSecurityFilterChain)

5.配置spring-security.xml核心配置文件

<?xml version="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
http://www.springframework.org/schema/security/spring-security.xsd"> <!--
① 配置哪些链接可以放行(没有认证通过也可以访问的资源)
security="none":没有权限
pattern="/login.html":没有任何权限,可以访问login.html
-->
<!--<security:http security="none" pattern="/login.html"></security:http>--> <security:http pattern="/login.html" security="none"></security:http> <!--
② 定义哪些链接不可以放行(必须通过认证才能访问的资源),及需要有角色,有权限才可以放行访问资源
<security:http auto-config="true" use-expressions="true">
auto-config="true":开启自动配置 由springsecurity提供登录页面,提供登录的url地址,退出的url地址
use-expressions="true":使用表达式的方式控制权限
security:intercept-url:定义哪些链接不可以放行,需要当前角色和权限才能放行
pattern="/**":要求系统中的所有资源,都必须通过角色和权限才能访问
access:指定角色和权限
如果使用表达式use-expressions="true"
access="hasRole('ROLE_ADMIN'):表示具有ROLE_ADMIN的角色才能访问系统的资源
如果不使用表达式use-expressions="false"
access="ROLE_ADMIN:表示具有ROLE_ADMIN的角色才能访问系统的资源
-->
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')"></security:intercept-url>
</security:http> <!--
③ 认证管理:定义登录账号和密码,并授予当前用户访问的角色或权限
用户名和密码:当前用户具有的角色,写死到配置文件中
security:user name="admin" :登录名
authorities="ROLE_ADMIN" :角色(ROLE_ADMIN),权限
password="admin" :密码
-->
<security:authentication-manager>
<security:authentication-provider>
<security:user-service>
<security:user name="admin" authorities="ROLE_ADMIN" password="admin"></security:user>
</security:user-service>
</security:authentication-provider>
</security:authentication-manager>
</beans>

注意:没有权限的和需要权限的顺序不可以颠倒

6.启动tomcat测试一下

访问login.html

访问index.html

当我们输入正确用户名和密码(admin/admin)访问受保护资源的时候直接报错了,因为 spring security 提供了一套安全机制,登录的时候进行了拦截,查看源码PasswordEncoderFactories发现默认使用的密码加密方式是new BCryptPasswordEncoder(),但是我们在Spring容器中并没有提供

这个可以后面加上,现在我们只需要修改配置文件

<security:user name="admin" authorities="ROLE_ADMIN" password="{noop}admin"></security:user>

{noop}:表示当前使用的密码为明文。表示当前密码不需要加密 PasswordEncoderFactories

7.到此完成了Spring Security的入门案例,但是前面还有好几个问题有待解决例如:

1、项目中我们将所有的资源(所有请求URL)都保护起来,实际环境下往往有一些资源不需要认证(例如login.html)也可以访问,也就是可以匿名访问。

(1):配置可匿名访问的资源,在webapp下创建static/imgs目录放入一张girl.jpg图片,重启项目

访问发现被拦截了

想让图片能访问,我们只需在spring-security.xml文件中配置,指定哪些资源可以匿名访问

<!--
http:用于定义相关权限控制
指定哪些资源不需要进行权限校验,可以使用通配符
-->
<security:http security="none" pattern="/static/imgs/**" />
<security:http security="none" pattern="/static/css/**" />
<security:http security="none" pattern="/static/js/**" />

2、登录页面是由框架生成的,而我们的项目往往会使用自己的登录页面。

(1):说实话SpringSecurity自带的登录页面挺丑的,所以我们可以使用指定的登录页面,怎么做呢?

(2):在webapp文件夹下面,提供login.html作为项目的登录页面

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
</head>
<body>
<h1>自定义登录页面</h1>
<form action="/login.do" method="post">
用户名: <input type="username" name="username"> <br>
密码: <input type="password" name="password"> <br>
<button type="submit">提交</button>
</form>
</body>
</html>



注意:要访问到这个页面前提是你配置了login.html资源可以匿名访问

 <security:http pattern="/login.html" security="none"></security:http>

(3):修改spring-security.xml文件,加入表单登录信息的配置

<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')"></security:intercept-url>
<!--
form-login:定义表单登录信息
login-page="/login.html":表示指定登录页面
username-parameter="username":使用登录名的名称,默认值是username
password-parameter="password":使用登录名的密码,默认值是password
login-processing-url="/login.do":表示登录的url地址
default-target-url="/index.html":登录成功后的url地址
authentication-failure-url="/login.html":认证失败后跳转的url地址,失败后指定/login.html
always-use-default-target="true":登录成功后,始终跳转到default-target-url指定的地址,即登录成功的默认地址
-->
<security:form-login
login-page="/login.html"
username-parameter="username"
password-parameter="password"
login-processing-url="/login.do"
default-target-url="/index.html"
authentication-failure-url="/login.html"
always-use-default-target="true"/>
</security:http>

访问试一下

注意:我们想要实现自定义登录页面,我们必须要配置将csrf禁用(可以观察SpringSecurity默认的登录是有一个),配置在security:http标签中

<!--
csrf:对应CsrfFilter过滤器
disabled:是否启用CsrfFilter过滤器,如果使用自定义登录页面需要关闭此项,否则登录操作会被禁用(403)
-->
<security:csrf disabled="true"/>

3、入门案例中我们直接将用户名和密码配置在了配置文件中,而真实生产环境下的用户名和密码往往保存在数据库中。

(1):准备一个数据库,添加表和相应的数据



(2):创建实体类User

package com.qbb.security.entity;

/**
* @author QiuQiu&LL (个人博客:https://www.cnblogs.com/qbbit)
* @version 1.0
* @date 2022-03-21 19:34
* @Description:
*/
public class User {
private Integer id;
private String username;
private String password; public User() {
} public User(Integer id, String username, String password) {
this.id = id;
this.username = username;
this.password = password;
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} @Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}

(3):操作数据库我使用的是mybaits

这里给大家推荐一个idea的maven搜索插件,在plugins搜maven-search

导入相关依赖
<?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> <groupId>com.qbb.security</groupId>
<artifactId>ssm-security</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<spring.version>5.0.5.RELEASE</spring.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<druid.version>1.2.6</druid.version>
<mybatis.version>3.5.7</mybatis.version>
<mysql.version>5.1.48</mysql.version>
<mybatis-spring.version>2.0.6</mybatis-spring.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.version}</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!--spring整合mybatis-->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis-spring.version}</version>
</dependency>
<!--数据源-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!--数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
修改web.xml
 <!-- 2:springmvc的核心控制器-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 指定加载的配置文件 ,通过参数contextConfigLocation加载 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
创建jdbc.properties,applicationContext.xml,SqlMapConfig.xml
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/qbbit3?useUnicode=true&characterEncoding=UTF-8
jdbc.user=root
jdbc.password=root ------------ <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <import resource="spring-security.xml"></import> <!--1.开启注解扫描-->
<context:component-scan base-package="com.qbb.security.**">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan> <!--2.加载配置文件-->
<context:property-placeholder location="classpath:jdbc.properties"/> <!--3.配置数据源信息-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.password}"/>
</bean> <!--4.配置SQLSessionFactory工厂-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--指定mybatis配置文件的位置-->
<property name="configLocation" value="classpath:SqlMapConfig.xml"/>
<!--指定数据源-->
<property name="dataSource" ref="dataSource"/>
<!--指定mapper配置文件的位置-->
<property name="mapperLocations" value="classpath*:mapper/**.xml"></property>
</bean> <!--5.配置AccountDao接口所在的包-->
<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--扫描所有的dao接口-->
<property name="basePackage" value="com.qbb.security.mapper"/>
</bean> </beans> ------------ <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!--控制mybatis全局行为-->
<settings>
<!--设置mybatis输出日志-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<!--驼峰命名规则-->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings> <!--设置别名-->
<typeAliases>
<package name="com.qbb.security.entity"/>
</typeAliases>
</configuration>

(4):创建UserMapper及其映射文件

创建UserService,UserMapper,UserMapper.xml

package com.qbb.security.service; import com.qbb.security.entity.User;
import com.qbb.security.mapper.UserMapper;
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.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component; import java.util.ArrayList;
import java.util.List; /**
* @author QiuQiu&LL (个人博客:https://www.cnblogs.com/qbbit)
* @version 1.0
* @date 2022-03-21 19:53
* @Description:
*/
@Component
public class UserService implements UserDetailsService { @Autowired
private UserMapper userMapper; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userMapper.login(username);
if (user == null) {
throw new RuntimeException("用户不存在");
}
////查询数据库获取的密码
String passwordInDb ="{noop}" + user.getPassword(); //授权,后期需要改为查询数据库动态获得用户拥有的权限和角色
List<GrantedAuthority> lists = new ArrayList<>();
lists.add(new SimpleGrantedAuthority("add"));
lists.add(new SimpleGrantedAuthority("delete"));
lists.add(new SimpleGrantedAuthority("ROLE_ADMIN")); //public User(String username, String password, Collection<? extends GrantedAuthority > authorities)
//返回User,
//参数一:存放登录名,
//参数二:存放数据库查询的密码(数据库获取的密码,默认会和页面获取的密码进行比对,成功跳转到成功页面,失败回到登录页面,并抛出异常表示失败)
//参数三:存放当前用户具有的权限集合 //注意:框架提供的User类:org.springframework.security.core.userdetails.User
return new org.springframework.security.core.userdetails.User(username,passwordInDb,lists);
}
} ------------ package com.qbb.security.service; import com.qbb.security.entity.User;
import com.qbb.security.mapper.UserMapper;
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.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component; import java.util.ArrayList;
import java.util.List; /**
* @author QiuQiu&LL (个人博客:https://www.cnblogs.com/qbbit)
* @version 1.0
* @date 2022-03-21 19:53
* @Description:
*/
@Component
public class UserService implements UserDetailsService { @Autowired
private UserMapper userMapper; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User user = userMapper.login(username); if (user == null) {
throw new RuntimeException("用户不存在");
}
//模拟数据库中的密码,后期需要查询数据库
String passwordInDb ="{noop}" + user.getPassword();
//授权,后期需要改为查询数据库动态获得用户拥有的权限和角色
List<GrantedAuthority> lists = new ArrayList<>();
lists.add(new SimpleGrantedAuthority("add"));
lists.add(new SimpleGrantedAuthority("delete"));
lists.add(new SimpleGrantedAuthority("ROLE_ADMIN")); //public User(String username, String password, Collection<? extends GrantedAuthority > authorities)
//返回User,
//参数一:存放登录名,
//参数二:存放数据库查询的密码(数据库获取的密码,默认会和页面获取的密码进行比对,成功跳转到成功页面,失败回到登录页面,并抛出异常表示失败)
//参数三:存放当前用户具有的权限集合 //注意:框架提供的User类:org.springframework.security.core.userdetails.User
return new org.springframework.security.core.userdetails.User(username,passwordInDb,lists);
}
} ------------ <?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.qbb.security.mapper.UserMapper">
<select id="login" resultType="com.qbb.security.entity.User">
select * from user where username = #{username}
</select>
</mapper>
修改spring-security.xml配置文件
 <security:authentication-manager>
<!-- authentication-provider:认证提供者,执行具体的认证逻辑 -->
<security:authentication-provider user-service-ref="userService"></security:authentication-provider>
<!--<security:authentication-provider>
<security:user-service>
<security:user name="admin" authorities="ROLE_ADMIN" password="{noop}admin"></security:user>
</security:user-service>
</security:authentication-provider>-->
</security:authentication-manager>

重启服务器测试

输入错误的用户名和密码,跳回登录页

输入正确的跳转到index.html

4、在配置文件中配置的密码使用明文,这非常不安全,而真实生产环境下密码需要进行加密。

对密码进行加密

创建一个测试类

package com.qbb.security;

import org.junit.Test;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; /**
* @author QiuQiu&LL (个人博客:https://www.cnblogs.com/qbbit)
* @version 1.0
* @date 2022-03-21 20:27
* @Description:
*/
public class TestBCryptPasswordEncoder { @Test
public void test01() {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
String pwd1 = encoder.encode("123");
String pwd2 = encoder.encode("123");
System.out.println("pwd1 = " + pwd1);
System.out.println("pwd2 = " + pwd2);
System.out.println(encoder.matches("123", pwd2));
}
}

从测试程序可以看出SpringSecurity加密还是狠安全的,接下来只需要在spring-security.xml中配置加密策略就好了

<!--配置密码加密对象-->
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder" /> <!-- authentication-provider:认证提供者,执行具体的认证逻辑 -->
<security:authentication-provider user-service-ref="userService">
<!--指定密码加密策略-->
<security:password-encoder ref="passwordEncoder"></security:password-encoder>
</security:authentication-provider>

测试,别忘了修改UserService

//查询数据库获取的密码
String passwordInDb =user.getPassword();

(5):配置多种校验规则(对页面)

首先在项目的webapp文件夹下面创建 a.html、b.html、c.html、d.html几个页面

修改spring-security.xml文件:前提:<security:http auto-config=“true” use-expressions=“true”>

<security:http auto-config="true" use-expressions="true">
<!--<security:intercept-url pattern="/**" access="hasRole('ROLE_ADMIN')"></security:intercept-url>--> <!--只要认证通过就可以访问-->
<security:intercept-url pattern="/index.html" access="isAuthenticated()" />
<security:intercept-url pattern="/a.html" access="isAuthenticated()" /> <!--拥有add权限就可以访问b.html页面-->
<security:intercept-url pattern="/b.html" access="hasAuthority('add')" /> <!--拥有ROLE_ADMIN角色就可以访问c.html页面,
注意:此处虽然写的是ADMIN角色,框架会自动加上前缀ROLE_-->
<security:intercept-url pattern="/c.html" access="hasRole('ROLE_ADMIN')" /> <!--拥有ROLE_ADMIN角色就可以访问d.html页面-->
<security:intercept-url pattern="/d.html" access="hasRole('ABC')" />
</security:http>

测试:d.html没有权限

前面我们在UserService中给了登录的该用户权限,所以a,b,c.html可以正常访问

 //授权,后期需要改为查询数据库动态获得用户拥有的权限和角色
List<GrantedAuthority> lists = new ArrayList<>();
lists.add(new SimpleGrantedAuthority("add"));
lists.add(new SimpleGrantedAuthority("delete"));
lists.add(new SimpleGrantedAuthority("ROLE_ADMIN"));

(6):注解方式权限控制(对类)

Spring Security除了可以在配置文件中配置权限校验规则,还可以使用注解方式控制类中方法的调用。例如:Controller中的某个方法要求必须具有某个权限才可以访问,此时就可以使用Spring Security框架提供的注解方式进行控制。粒度是真的细...

修改applicationContext.xml

<context:component-scan base-package="com.qbb.security.**"></context:component-scan>

修改spring-security.xml

<!--开启注解方式权限控制-->
<security:global-method-security pre-post-annotations="enabled" />

创建HelloController类并在Controller的方法上加入注解(@PreAuthorize)进行权限控制

package com.qbb.security.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*; /**
* @author QiuQiu&LL (个人博客:https://www.cnblogs.com/qbbit)
* @version 1.0
* @date 2022-03-21 19:51
* @Description:
*/
@RestController
@RequestMapping("/hello")
public class HelloController { @GetMapping("/get")
@PreAuthorize("hasAnyAuthority('delete')")
public String get() {
return "get";
} @PostMapping("/post")
@PreAuthorize("hasAnyAuthority('add')")
public String post() {
return "post";
} @PutMapping("/put")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public String put() {
return "put";
} @DeleteMapping("/delete")
@PreAuthorize("hasRole('delete')")
public String delete() {
return "delete";
} }

注意:使用PostMan 或者 ApiFox测试

(7): 退出登录

用户完成登录后Spring Security框架会记录当前用户认证状态为已认证状态,即表示用户登录成功了。那用户如何退出登录呢?我们可以在spring-security.xml文件中进行如下配置:

修改index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
登录成功!<br>
<a href="/logout.do">退出登录</a>
</body>
</html>

修改springsecurity.xml

 <!--
logout:退出登录
logout-url:退出登录操作对应的请求路径
logout-success-url:退出登录后的跳转页面
invalidate-session="true" 默认为true,用户在退出后Http session失效
-->
<security:logout logout-url="/logout.do" invalidate-session="true" logout-success-url="/login.html"></security:logout>

测试一下,没有问题

至此SpringSecurity入门完成,更过详细的用法可以参考SpringSecurity中文网

SpringSecurity入门(SSM版)的更多相关文章

  1. 模仿天猫实战【SSM版】——后台开发

    上一篇文章链接:模仿天猫实战[SSM版]--项目起步 后台需求分析 在开始码代码之前,还是需要先清楚自己要做什么事情,后台具体需要实现哪些功能: 注意: 订单.用户.订单.推荐链接均不提供增删的功能. ...

  2. Bootstrap fileinput v3.0(ssm版)

    说明在上一个版本即Bootstrap fileinput v2.0(ssm版)的基础上,增加了多处都需要上传的需求 核心代码ArticleController.java package com.isd ...

  3. SpringSecurity 在 SSM架构中的使用

    SpringSecurity - SSM SpringSecurity 对比 Shiro SpringSecurity的特点: 能和 Spring无缝贴合 能实现全面的权限控制 专门为 Web开发而设 ...

  4. springSecurity入门小demo--配置文件xml的方式

    本例子只是一个最最最简单的入门demo,重点讲解xml的配置参数的意思和遇到的坑,主要的功能有: 自定义登录页面,错误页面 配置角色 csrf-403报错解决方法(加上一行代码配置就ok) 后台ifr ...

  5. SSM+Maven(教程二):Idea快速入门SSM+Maven框架。

    快速入门须知 这篇文章,直接应用已经搭建好的SSM框架.一般在公司里面,考虑框架的搭建.封装等问题,都由研发经理或者架构师完成,所以对于刚入门的小白来说,在去搭建整合花费的时间会很多很多.对于理解能力 ...

  6. 狂神——SpringSecurity入门例子(设置不同用户访问权限)

    文章目录 简介 SpringSecurity环境搭建 实现界面的路由跳转 效果 用户认证和授权 授权 认证 效果 注销及权限控制 注销 权限控制 记住我及首页定制 参考资料 简介 狂神的Springb ...

  7. 模仿天猫实战【SSM版】——项目起步

    前言:现在自己的学习似乎遇到了瓶颈,感觉学习了 SSM 之后有一些迷茫,不知道接下来该往哪里去努力了,我觉得这是个很不好的状态,为了度过这段时期,我准备把天猫模仿下来(给自己找点事做)之后开始去巩固 ...

  8. SpringSecurity入门demo

    配置依赖: <properties> <spring.version>4.2.4.RELEASE</spring.version> </properties& ...

  9. IDEA快速入门(Mac版)

    [持续更新]一篇今年年头的老文章顺道发布了,大家有任何问题可以留言沟通.当时刚刚加入团团,愿大家有机会还是购买一台MAC,确实能给大家的效率赋能,虽然在一开始会有一些艰难!⛽️ 望借着换工作的东风,好 ...

  10. ActiveMQ 入门Nodejs版

    ActiveMQ 入门下载与安装 官方下载地址 解压,运行bin/win[32|64]/activemq[.bat] 启动服务 环境信息 控制台: http://localhost:8161 默认端口 ...

随机推荐

  1. tcpdump后台不间断抓包

    版本1的抓包命令 这两天排查一个小问题,需要在服务器上使用tcpdump24小时不间断抓包,这里简单记录下. 先看下tcpdump的语法: tcpdump [ -AbdDefhHIJKlLnNOpqS ...

  2. 使用ensp搭建路由拓扑,并使用isis协议实现网络互通实操

    转载请注明出处: 1.通过拓扑搭建如下拓扑: 其中R7.R8为L1,R6为L1/2,R9为L2. 2.配置isis实现网络互通 R7配置如下: [Huawei]isis 1 [Huawei-isis- ...

  3. Python面向对象——1、什么是异常 2、为何处理异常 3、如何处理异常? 4、何时使用异常处理 网络编程的一些预备知识

    文章目录 异常 1.什么是异常 2.为何处理异常 3.如何处理异常? 4.何时使用异常处理 网络编程的一些预备知识 异常 1.什么是异常 异常是程序发生错误的信号.程序一旦出现错误,便会产生一个异常, ...

  4. MySQL5.7版本单节点大数据量迁移到PXC8.0版本集群全记录-3

    接上文,单节点升级到80版本之后,构建新版本的80集群就水到渠成.相对简单了,详情可参见之前的集群构建博文. 本文在修改配置集群的新参数时,修改了pxc_strict_mode为默认的ENFORCIN ...

  5. QUERIES

    这个题解..u1s1我没看懂,但是我觉得这里面有一个重要的思想就是对于像异或这种最终值只是看一个数位的问题,我们可以考虑分解,把每一个子问题单独解决就可以了其实更难的应该是每个子区间的异或和之和这个方 ...

  6. 普冉PY32系列(九) GPIO模拟和硬件SPI方式驱动无线收发芯片XL2400

    目录 普冉PY32系列(一) PY32F0系列32位Cortex M0+ MCU简介 普冉PY32系列(二) Ubuntu GCC Toolchain和VSCode开发环境 普冉PY32系列(三) P ...

  7. 【实操】Java+百度ocr,实现图片识别文字小工具

    前言 缘由 图片识别文字,咱用java也可以 通过java+百度ocr,实现一个截图或上传图片,图片识别文字的小工具.并通过exe4j工具将jar包封装成exe可执行桌面文件,方便使用及学习. Tip ...

  8. GPL协议原文及中文翻译

    GPL协议原文及中文翻译 原文参考链接 翻译参考链接 原文 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 19 ...

  9. 你也许不再需要使用 CSS Media Queries(媒体查询)了

    你也许不再需要使用 CSS Media Queries(媒体查询)了 最近,CSS 引入了一项新功能:Container Queries.它可以替代 Media Queries 并实现 Media Q ...

  10. js数据结构--散列表

    <!DOCTYPE html> <html> <head> <title></title> </head> <body&g ...