Spring Security 学习笔记
1、认证和授权
关于认证和授权,查资料是这样解释的
认证:系统提供的用于识别用户身份的功能,通常提供用户名和密码进行登录其实就是在进行认证,认证的目的是让系统知道你是谁。
授权:用户认证成功后,需要为用户授权,其实就是指定当前用户可以操作哪些功能。
先认证后授权
2、权限模块数据模型
要实现最终的权限控制,需要有一套数据模型来做支撑,一般的表结构如下:
用户表——权限表——角色表——菜单表——用户角色关系表——角色权限关系表——角色菜单关系表

类似上面这种表结构
认证的过程:只需要用户表,在登录时查询用户信息,判断用户名和密码是否正确。这一过程较为简单
授权的过程:用户必须完成认证之后才可以进行授权,首先可以根据用户查询其角色,再根据角色查询对应的菜单,这样就确定了用户能够看到哪些菜单。然后再根据用户的角色查询对应的权限,这样就确定了用户拥有哪些权限。所以授权过程会用到上面7张表。
3、Spring Security
SS是spring提供的安全认证服务框架。使用ss可以帮助我们简化认证和授权的过程。
这是他的官网:https://docs.spring.io/spring-security/site/docs/5.4.5/reference/html5/
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
3.1、工程搭建
创建maven工程,打包方式为war包,把需要的依赖文件添加到pom.xml文件中。
如果需要tomcat插件,需进行以下配置:
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<!-- 指定端口 -->
<port>85</port>
<!-- 请求路径 -->
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
提供index.html文件,提供内容Hello Spring Security!
3.2、配置web.xml
在web.xml中配置SpringMVC中的DisPatcherServlet和用于整合第三方框架的DelegatingFilterProxy,用于整合spring Security。
<web-app>
<display-name>Archetype Created Web Application</display-name>
<filter>
<!--
DelegatingFilterProxy用于整合第三方框架
整合Spring Security时过滤器的名称必须为springSecurityFilterChain,
否则会抛出NoSuchBeanDefinitionException异常
-->
<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>
<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>
注意:DelegatingFilterProxy用于整合第三方框架 整合Spring Security时过滤器的名称必须为springSecurityFilterChain,否则会抛出NoSuchBeanDefinitionException异常
3.3 配置 spring-security.xml
在spring-security.xml中主要配置认证规则和拦截管理器。
3.3 运行测试
访问localhost:85/index.html

因为没有权限,所以跳转到spring security自带的登录页面。
进行登录后,重新访问

访问成功了!
4、对入门案例进行改进
前面我们已经完成了Spring Security的入门案例,通过入门案例我们可以看到,Spring Security将我们项目中的所有资源都保护了起来,要访问这些资源必须要完成认证而且需 要具有ROLE_ADMIN角色。
但是入门案例中的使用方法离我们真实生产环境还差很远,还存在如下一些问题:
1、项目中我们将所有的资源(所有请求URL)都保护起来,实际环境下往往有一些资源 不需要认证也可以访问,也就是可以匿名访问。 access="hasRole('ROLE_ADMIN')" />
2、登录页面是由框架生成的,而我们的项目往往会使用自己的登录页面。
3、直接将用户名和密码配置在了配置文件中,而真实生产环境下的用户名和密码往往保存在数据库中。
4、在配置文件中配置的密码使用明文,这非常不安全,而真实生产环境下密码需要进行 加密。
4.1配置可匿名访问的资源
因为上面的配置中“/**”代表对所有的资源都进行权限的判断,但实际生产环境中,我们并不需要将所有的页面都进行权限配置比如登录页面。
所以我们需要进行下面的配置:
<security:http security="none" pattern="/pages/a.html"></security:http>
<security:http security="none" pattern="/pages/b.html"></security:http>
然后再运行测试,发现a.html和b.html可以访问,之前的index.html任然需要登录才可以进入。

4.2 配置自己自定义的登录页面
准备工作:一个自定义的登录页面,放入相应的目录中
-
配置该页面可匿名访问
<security:http security="none" pattern="/pages/login.html"></security:http>
-
如果我们使用自己的登录页面,必须配置登录表单,页面提交的登录请求由框架处理
<security:form-login
login-page="/pages/login.html"
username-parameter="username"
password-parameter="password"
login-processing-url="/login.do"
default-target-url="/index.html"
authentication-failure-url="/pages/login.html"
></security:form-login>
login-page="/pages/login.html":表单页面
username-parameter="username" password-parameter="password" :相对应的用户名和密码
default-target-url="/index.html" authentication-failure-url="/pages/login.html" :登录成功和失败所对应的页面
-
关闭CsrfFilter过滤器,默认开启
<!‐‐
csrf:对应CsrfFilter过滤器
disabled:是否启用CsrfFilter过滤器,如果使用自定义登录页面需要关闭此项,否则
登录操作会被禁用(403)
‐‐>
<security:csrf disabled="true"></security:csrf>
为什么关闭csrs过滤器,因为在使用默认的登录界面,会有一个隐藏域生成一个随机值,框架进行对比,如果不一致,会认为这是伪造的认证请求,登录操作会被禁用。
4.3从数据库查询信息(首先通过map模拟数据库)
如果我们要从数据库动态查询用户信息,就必须按照spring security框架的要求提供一个 实现UserService接口的实现类,并按照框架的要求进行配置即可。框架会自动调用实现类中的方法并自动进行密码校验。
实现代码:
先通过map集合模拟数据库查询
public class SpringSercuity implements UserDetailsService {
public static Map<String,User> map=new HashMap<>();
static {
User user=new User();
user.setUsername("xiaohong");
user.setPassword("123456");
User user1=new User();
user1.setUsername("xiaoming");
user1.setPassword("123456");
map.put(user.getUsername(),user);
map.put(user1.getUsername(),user1);
}
4.4 对密码进行加密
前面我们使用的密码都是明文的,这是非常不安全的。一般情况下用户的密码需要进行 加密后再保存到数据库中。
常见的密码加密方式有: 3DES、AES、DES:使用对称加密算法,可以通过解密来还原出原始密码
MD5、SHA1:使用单向HASH算法,无法通过计算还原出原始密码,但是可以建立彩虹表进行查表破解
bcrypt:将salt随机并混入最终加密后的密码,验证时也无需单独提供之前的salt,从而 无需单独处理salt问题 加密后的格式一般为:
$2a$10$/bTVvqqlH9UiE0ZJZ7N2Me3RIgUCdgMheyTgV0B4cMCSokPa.6oCa
加密后字符串的长度为固定的60位。其中:$是分割符,无意义;2a是bcrypt加密版本 号;10是cost的值;而后的前22位是salt值;再然后的字符串就是密码的密文了。

实现步骤:
-
配置文件中添加相关的加密对象的bean
<!-- 配置密码加密对象-->
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
-
自动注入
-
调用自带方法,实现密码加密
User user=new User();
user.setUsername("xiaohong");
//使用BCrypt对密码进行加密
user.setPassword(passwordEncoder.encode("admin"));
User user1=new User();
user1.setUsername("xiaoming");
user1.setPassword(passwordEncoder.encode("admin"));
4.5 配置多种校验规则
为了测试方便,首先在项目中创建a.html、b.html、c.html、d.html几个页面 修改spring-security.xml文件:
<!‐‐只要认证通过就可以访问‐‐>
<security:intercept‐url pattern="/index.jsp" 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页面‐‐>
<security:intercept‐url pattern="/c.html" access="hasRole('ROLE_ADMIN')"
/>
<!‐‐拥有ROLE_ADMIN角色就可以访问d.html页面,
注意:此处虽然写的是ADMIN角色,框架会自动加上前缀ROLE_‐‐>
<security:intercept‐url pattern="/d.html" access="hasRole('ADMIN')" />
记得把上面案例用到的校验规则移除
access="hasRole('ROLE_ADMIN')==access="hasRole('ADMIN')":框架会自动加入ROLE_
4.6 注解方式权限控制
Spring Security除了可以在配置文件中配置权限校验规则,还可以使用注解方式控制类 中方法的调用。
例如Controller中的某个方法要求必须具有某个权限才可以访问,此时就可以使用Spring Security框架提供的注解方式进行控制。
实现步骤:
第一步:在spring-security.xml文件中配置组件扫描,用于扫描Controller
<mvc:annotation‐driven></mvc:annotation‐driven> <context:component‐scan base‐package="com.itheima.controller"> </context:component‐scan>
第二步:在spring-security.xml文件中开启权限注解支持
<!‐‐开启注解方式权限控制‐‐> <security:global‐method‐security pre‐post‐annotations="enabled" />
第三步:创建Controller类并在Controller的方法上加入注解进行权限控制
4.7 退出登录
用户完成登录后Spring Security框架会记录当前用户认证状态为已认证状态,即表示用 户登录成功了。那用户如何退出登录呢?
我们可以在spring-security.xml文件中进行如下配置:
<!‐‐logout:退出登录
logout‐url:退出登录操作对应的请求路径 logout‐success‐url:
退出登录后的跳转页面 ‐‐>
<security:logout
logout‐url="/logout.do"
logout‐success‐url="/login.html"
invalidate‐ session="true"/>

浙公网安备 33010602011771号