03SSM综合案例之SpringSecurity

Posted teayear

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了03SSM综合案例之SpringSecurity相关的知识,希望对你有一定的参考价值。

day03_SSM综合案例

一、课程目标

1. 【理解】SpringSecurity权限框架
2. 【掌握】使用SpringSecurity进行用户登录
3. 【掌握】资源权限管理

二、SpringSecurity

2.1 什么是SpringSecurity

Spring Security 的前身是 Acegi Security ,是 Spring 项目组中用来提供安全认证服务的框架

(https://projects.spring.io/spring-security/) Spring Security 为基于J2EE企业应用软件提供了全面安全服务。特别是使用领先的J2EE解决方案-Spring框架开发的企业软件项目。人们使用Spring Security有很多种原因,不过通常吸引他们的是在J2EE Servlet规范或EJB规范中找不到典型企业应用场景的解决方案。特别要指出的是他们不能再

WAR 或 EAR 级别进行移植。这样,如果你更换服务器环境,就要,在新的目标环境进行大量的工作,对你的应用

系统进行重新配置安全。使用Spring Security 解决了这些问题,也为你提供很多有用的,完全可以指定的其他安

全特性。安全包括两个主要操作

  • “认证”,是为用户建立一个他所声明的主体。主体一般是指用户,设备或可以在你系统中执行动作的其他系

统。(可以将主体当前权限框架自己的session,认证其实就是登录操作,并将登录成功的数据信息存入主体)

  • “授权”,指的是一个用户能否在你的应用中执行某个操作,在到达授权判断之前,身份的主题已经由身份验证

过程建立了。(查询是否对应权限,授权其实就是在认证之后请求需要权限的资源时,查询数据库在主体中保存对应权限数据)

这些概念是通用的,不是Spring Security特有的。在身份验证层面,Spring Security广泛支持各种身份验证模式,

这些验证模型绝大多数都由第三方提供,或则正在开发的有关标准机构提供的,例如 Internet Engineering Task

Force.作为补充,Spring Security 也提供了自己的一套验证功能。

Spring Security 目前支持认证一体化如下认证技术:

HTTP BASIC authentication headers (一个基于IEFT RFC 的标准)

HTTP Digest authentication headers (一个基于IEFT RFC 的标准)

HTTP X.509 client certi?cate exchange(一个基于IEFT RFC 的标准)

LDAP (一个非常常见的跨平台认证需要做法,特别是在大环境)

Form-based-authentication (提供简单用户接口的需求)

OpenID authentication Computer Associates Siteminder JA-SIG Central Authentication Service (CAS,这是一个流行的开源单点登录系统)

Transparent authentication context propagation for Remote Method Invocation and HttpInvoker (一个Spring远程调用协议)

2.2 核心组件

SecurityContextHolder

SecurityContextHolder它持有的是安全上下文 (security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权等等,这些都被保存在SecurityContextHolder中。SecurityContextHolder默认使用ThreadLocal 策略来存储认证信息。看到 ThreadLocal 也就意味着,这是一种与线程绑定的策略。在web环境下,Spring Security在用户登录时自动绑定认证信息到当前线程,在用户退出时,自动清除当前线程的认证信息

看源码他有静态方法

//获取 上下文
  public static SecurityContext getContext() 
        return strategy.getContext();
    
  //清除上下文  
  public static void clearContext() 
        strategy.clearContext();
    

SecurityContextHolder.getContext().getAuthentication().getPrincipal()
getAuthentication() 返回了认证信息,

getPrincipal() 返回了身份信息

UserDetails 便是Spring对身份信息封装的一个接口

SecurityContext

安全上下文,主要持有 Authentication 对象,如果用户未鉴权,那Authentication对象将会是空的。看源码可知

package org.springframework.security.core.context;

import java.io.Serializable;
import org.springframework.security.core.Authentication;

public interface SecurityContext extends Serializable 
    Authentication getAuthentication();
    void setAuthentication(Authentication var1);

Authentication

鉴权对象,该对象主要包含了用户的详细信息 (UserDetails) 和用户鉴权时所需要的信息,如用户提交的用户名密码、Remember-me Token,或者digest hash值等,按不同鉴权方式使用不同的 Authentication 实现,看源码可知道

package org.springframework.security.core;

import java.io.Serializable;
import java.security.Principal;
import java.util.Collection;

public interface Authentication extends Principal, Serializable 
    Collection<? extends GrantedAuthority> getAuthorities();

    Object getCredentials();
    Object getDetails();
    Object getPrincipal();
    boolean isAuthenticated();
    void setAuthenticated(boolean var1) throws IllegalArgumentException;


注意 GrantedAuthority 该接口表示了当前用户所拥有的权限(或者角色)信息。这些信息由授权负责对象 AccessDecisionManager 来使用,并决定最终用户是否可以访问某 资源(URL或方法调用或域对象)。鉴权时并不会使用到该对象

UserDetails

这个接口规范了用户详细信息所拥有的字段,譬如用户名、密码、账号是否过期、是否锁定等。在Spring Security中,获取当前登录的用户的信息,一般情况是需要在这个接口上面进行 扩展,用来对接自己系统的用户,看源码可知

package org.springframework.security.core.userdetails;

import java.io.Serializable;
import java.util.Collection;
import org.springframework.security.core.GrantedAuthority;

public interface UserDetails extends Serializable 
    Collection<? extends GrantedAuthority> getAuthorities();
    String getPassword();
    String getUsername();
    boolean isAccountNonExpired();
    boolean isAccountNonLocked();
    boolean isCredentialsNonExpired();
    boolean isEnabled();

UserDetailsService

这个接口只提供一个接口 loadUserByUsername(String username) ,这个接口非常 重要, 一般情况我们都是通过 扩展 这个接口来显示获取我们的用户信息,用户登陆时传递的用户名和密码也是通过这里这查找出来的用户名和密码进行校验,但是真正的校验不在这里,而是由 AuthenticationManager 以及 AuthenticationProvider 负责的,需要强调的是,如果用户不存在,不应返回 NULL,而要抛出异常 UsernameNotFoundException,看源码可知

package org.springframework.security.core.userdetails;

public interface UserDetailsService 
    UserDetails loadUserByUsername(String var1) throws UsernameNotFoundException;

2.4 SpringSecurity快速入门

创建测试web工程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xzA7lml2-1666446103170)(assets/image-20201011212908786.png)]

导入依赖

<dependencies>
    <!--springMVC-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <!--servlet-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>javax.servlet-api</artifactId>
      <version>4.0.1</version>
      <scope>provided</scope>
    </dependency>
    <!--jsp-->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.0</version>
      <scope>provided</scope>
    </dependency>
    <!--jstl-->
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
    </dependency>
    <!--jsckson -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.9</version>
    </dependency>
    <!--文件上传-->
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.4</version>
    </dependency>

    <!--spring相关坐标-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.5</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>

    <!--mybatis相关坐标-->
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.47</version>
    </dependency>
    <!--数据库连接池-->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.15</version>
    </dependency>
    <!--mybatis-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.6</version>
    </dependency>
    <!--spring-mybatis坐标-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.2</version>
    </dependency>
    <!--lombok-->
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.10</version>
    </dependency>
    <!--分页插件-->
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper</artifactId>
      <version>5.1.10</version>
    </dependency>

    <!--junit单元测试-->
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>

    <!--spring-security-->
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-web</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-config</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-core</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-taglibs</artifactId>
      <version>5.2.9.RELEASE</version>
    </dependency>

    <dependency>
      <groupId>javax.annotation</groupId>
      <artifactId>jsr250-api</artifactId>
      <version>1.0</version>
    </dependency>
    <!--log4j依赖-->
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
  </dependencies>

web.xml

<?xml version="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>contextConfigLocation</param-name>
		<param-value>classpath:spring-security.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<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>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
</web-app>

spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:security="http://www.springframework.org/schema/security"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       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:http auto-config="true" use-expressions="false" >
        <!--
        intercept-url定义一个过滤规则pattern表示对哪些url进行权限控制,ccess属性表示在请求对应的URL时需要什么权限,
        默认配置时它应该是一个以逗号分隔的角色列表,请求的用户只需拥有其中的一个角色就能成功访问对应的URL-->
        <security:intercept-url pattern="/**" access="ROLE_USER" />
        <!--<security:form-login />-->
    </security:http>
    <security:authentication-manager>
        <security:authentication-provider>
            <security:user-service>
                <security:user name="user" password="noopuser"
                               authorities="ROLE_USER" />
                <security:user name="admin" password="noopadmin"
                               authorities="ROLE_ADMIN" />
            </security:<

以上是关于03SSM综合案例之SpringSecurity的主要内容,如果未能解决你的问题,请参考以下文章

JAVAEE框架技术之14SSM综合案例

JAVAEE框架技术之14SSM综合案例 产品管理CRUD

JAVAEE框架技术之17之SSM综合案例 角色管理

JAVAEE框架技术之17之SSM综合案例 角色管理

SSM综合案例之角色管理实战

JAVAEE框架技术之15SSM综合案例 订单管理查询