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. MIT 6.828 Lab实验记录 —— lab1 Booting PC

    实验参考信息 MIT 6.828 lab1 讲义地址 MIT 6.828 课程 Schedule MIT 6.828 lab 环境搭建参考 MIT 6.828 lab 工具guide Brennan' ...

  2. Java 中的日期时间总结

    前言 大家好,我是 god23bin,在日常开发中,我们经常需要处理日期和时间,日期和时间可以说是一定会用到的,现在总结下 Java 中日期与时间的基本概念与一些常用的用法. 基本概念 日期(年月日, ...

  3. 面霸的自我修养:ThreadLocal专题

    王有志,一个分享硬核Java技术的互金摸鱼侠 加入Java人的提桶跑路群:共同富裕的Java人 今天是<面霸的自我修养>第5篇文章,我们一起来看看面试中会问到哪些关于ThreadLocal ...

  4. C#开发的基础工具类集合 - 开源研究系列文章

    今天发布一个基础工具类代码集合. 以前有发布过一个类似的类库(见博文: Magical平台类库代码分享 ),不过那个版本有点久了,也没有这次这个全面,这次发布的是一个很多地方用到的基础类库代码. 1. ...

  5. Java开发面试--nacos专区

    1. Nacos是什么? 请简要介绍Nacos是什么以及它的主要功能和用途. 答: 简介: Nacos是一个开源的.高性能.动态服务发现.配置和服务管理平台,通常用于微服务架构中.Nacos的名称来源 ...

  6. EXE一机一码打包加密大师(EXE加密, 一机一码, 添加授权,添加静态密码,支持设置试用时间)

    EXE一机一码打包加密大师可以打包加密保护EXE文件,同时给EXE文件添加上一机一码认证,或者静态密码,不同的电脑打开加密后的文件需要输入不同的激活码才能正常使用,保护文件安全,方便向用户收费. 下载 ...

  7. KRPano插件一键解密大师 支持最新版KRPano XML/JS解密 ,支持分析下载静态/动态网站资源

    KRPano插件一键解密大师,可以一键解密KRPano的XML/JS插件,并可以分析下载静态和动态网站的所有资源.软件下载安装即可使用,解密仅需鼠标一键点击即可,无需配置任何开发环境,方便全景开发人员 ...

  8. AK、SK实现(双方API交互:签名及验证)

    参考:https://blog.csdn.net/yqwang75457/article/details/117815474 1.原理 AK/SK: AK:Access Key Id,用于标示用户. ...

  9. Mac 下使用 ffmpeg 制作 gif

    Mac 下使用 ffmpeg 制作 gif 公众号文章,gif要求  300帧数以内        .以下是从 mp4 转为 gif 的步骤. 步骤 ffmpeg 是著名的视频处理开源软件 brew ...

  10. Java并发编程和多线程的区别

    并发编程: 并发编程是一种编程范式,它关注的是编写能够正确和高效处理多个并发任务的程序.并发编程不仅包括多线程,还包括了处理多个独立任务的各种技术和模式,如进程.协程.分布式编程等.并发编程的目标是实 ...