Spring Securit学习笔记之SS环境入门开发

Spring Securit学习笔记之SS环境入门开发

1. Spring+SpringMVC+Spring Security环境整合

1. 创建Maven项目,配置pom.xml文件

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
	
	<!-- 确定版本号 -->
    <spring.version>4.3.10.RELEASE</spring.version>
    <spring.security.version>4.2.3.RELEASE</spring.security.version>
    <jstl.version>1.2</jstl.version>
    <servlet.version>2.5</servlet.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>

    <!-- Spring 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>

    <!-- Spring Security dependencies -->
    <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>

    <!-- jstl for jsp page dependencies -->
    <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>${jstl.version}</version>
    </dependency>

    <!-- servlet-api dependencies -->
    <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>${servlet.version}</version>
      <scope>provided</scope>
    </dependency>

  </dependencies>

2. 创建Spring核心配置文件spring-core.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:context="http://www.springframework.org/schema/context"
       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/context
    http://www.springframework.org/schema/context/spring-context.xsd
    http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop.xsd">

</beans>

3. 创建SpringMVC配置文件spring-mvc.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:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       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 http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 开启控制器注解扫描 -->
    <context:component-scan base-package="com.example.controller"></context:component-scan>

    <!-- 开启springmvc注解扫描驱动 -->
    <mvc:annotation-driven></mvc:annotation-driven>

    <!-- 过滤静态资源,静态资源不做处理 -->
    <!--<mvc:default-servlet-handler></mvc:default-servlet-handler>-->

    <!-- 配置试图解析器 -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <!-- 配置前缀 -->
        <property name="prefix" value="/jsp/"></property>
        <!-- 配置后缀 -->
        <property name="suffix" value=".jsp"></property>
    </bean>

</beans>

4. 创建Spring Security配置文件spring-security.xml

1. 通过< security:http-basic /> 方式的权限登录认证

配置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-4.2.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.2.xsd">

    <!-- <security:http>: spring 过滤器链配置:
        1)需要拦截什么资源
        2)什么资源什么角色权限
        3)定义认证方式:HttpBasic,FormLogin(*)
        4)定义登录页面,定义登录请求地址,定义错误处理方式
    -->
    <security:http>
        <!--
            pattern: 需要拦截资源
            access: 拦截方式
                isFullyAuthenticated(): 该资源需要认证才可以访问
                isAnonymous():只有匿名用户才可以访问(如果登录用户就无法访问)
                permitAll():允许所有人(匿名和登录用户)访问
        -->
        <security:intercept-url pattern="/product/index" access="permitAll()"/>
        <security:intercept-url pattern="/**" access="isFullyAuthenticated()"/>

        <!-- security:http-basic: 使用 HttpBasic 方式进行登录(认证) -->
        <security:http-basic/>

    </security:http>

    <!--
        security:authentication-manager: 认证管理器
        1)认证信息提供方式(账户名,密码,当前用户权限)
    -->
    <security:authentication-manager>
        <security:authentication-provider>
            <security:user-service>
                <security:user name="user" password="user" authorities="ROLE_USER"/>
                <security:user name="user" password="user" authorities="ROLE_USER,ROLE_USER"/>
            </security:user-service>
        </security:authentication-provider>
    </security:authentication-manager>
</beans>

2. 通过< security:form-login /> 方式的权限登录认证

配置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-4.2.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.2.xsd">

    <!-- <security:http>: spring 过滤器链配置:
        1)需要拦截什么资源
        2)什么资源什么角色权限
        3)定义认证方式:HttpBasic,FormLogin(*)
        4)定义登录页面,定义登录请求地址,定义错误处理方式
    -->
    <security:http>
        <!--
            pattern: 需要拦截资源
            access: 拦截方式
                isFullyAuthenticated(): 该资源需要认证才可以访问
                isAnonymous():只有匿名用户才可以访问(如果登录用户就无法访问)
                permitAll():允许所有人(匿名和登录用户)访问
        -->
        <security:intercept-url pattern="/product/index" access="permitAll()"/>
        <security:intercept-url pattern="/**" access="isFullyAuthenticated()"/>

        <!-- security:form-login: 使用 FormLogin 方式进行登录(认证) -->
        <security:form-login/>
		<!--security:form-login有以下属性,可根据需求使用
            
            login-page: 自定义登录页面,默认为/login
            login-processing-url:登录请求拦截的url,也就是form表单提交时指定的action
            default-target-url 默认登录成功后跳转的url
            always-use-default-target 是否总是使用默认的登录成功后跳转url
            authentication-failure-url 登录失败后跳转的url
            username-parameter 用户名的请求字段 默认为userName
            password-parameter 密码的请求字段 默认为password
            authentication-success-handler-ref 指向一个AuthenticationSuccessHandler用于处理认证成功的请求,不能和default-target-url还有always-use-default-target同时使用
            authentication-success-forward-url 用于authentication-failure-handler-ref
            authentication-failure-handler-ref 指向一个AuthenticationFailureHandler用于处理失败的认证请求
            authentication-failure-forward-url 用于authentication-failure-handler-ref
            authentication-details-source-ref 指向一个AuthenticationDetailsSource,在认证过滤器中使用
        -->
    </security:http>

    <!--
        security:authentication-manager: 认证管理器
        1)认证信息提供方式(账户名,密码,当前用户权限)
    -->
    <security:authentication-manager>
        <security:authentication-provider>
            <security:user-service>
                <security:user name="user" password="user" authorities="ROLE_USER"/>
                <security:user name="user" password="user" authorities="ROLE_USER,ROLE_USER"/>
            </security:user-service>
        </security:authentication-provider>
    </security:authentication-manager>
</beans>

5. 配置文件web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">

  <!-- SpringSecurity 过滤器链 -->
  <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>

  <!-- 启动 Spring 配置spring工厂监听器 -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <!-- 全局加载配置文件 -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
      classpath:/spring-core.xml
      classpath:/spring-security.xml
    </param-value>
  </context-param>

  <!-- 启动 SpringMVC 配置核心入口servlet -->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!-- 指定servlet去哪加载springmvc的配置文件 -->
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:/spring-mvc.xml</param-value>
    </init-param>
    <!-- 服务器启动加载 Servlet 优先级 -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

6. 创建页面

Spring Securit学习笔记之SS环境入门开发

  1. index.jsp
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
        <a href="/product/add">add</a>
        <a href="/product/delete">delete</a>
        <a href="/product/list">list</a>
        <a href="/product/update">update</a>
    </body>
    </html>
    
  2. productAdd.jsp、productDelete.jsp、productList.jsp、productUpdate.jsp
    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    <h1>欢迎</h1>
    <a href="/product/index">index</a>
    </body>
    </html>
    

7. 开发controller

package com.example.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/product")
public class ProductController {
    /**
     * 商品添加
     */
    @RequestMapping("/index")
    public String index(){
        return "index";
    }
    /**
     * 商品添加
     */
    @RequestMapping("/add")
    public String add(){
        return "product/productAdd";
    }
    /**
     * 商品修改
     */
    @RequestMapping("/update")
    public String update(){
        return "product/productUpdate";
    }
    /**
     * 商品查询
     */
    @RequestMapping("/list")
    public String list(){
        return "product/productList";
    }
    /**
     * 商品删除
     */
    @RequestMapping("/delete")
    public String delete(){
        return "product/productDelete";
    }
}

2. 自定义登录页面

1. 开发登录界面

<%@page pageEncoding="UTF-8" %>
<html>
	<head>
	    <meta charset="UTF-8">
	    <title>Title</title>
	</head>
	<body>
		<h2>Hello World!</h2>
		<h3>表单登录</h3>
		<form action="/login" method="post">
		    <table>
		        <tr>
		            <td>用户名:</td>
		            <td><input type="text" name="username"></td>
		        </tr>
		        <tr>
		            <td>密码:</td>
		            <td><input type="password" name="password"></td>
		        </tr>
		        <tr>
		            <td colspan="2"><button type="submit">登录</button></td>
		        </tr>
		    </table>
		</form>
	</body>
</html>

2. 配置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-4.2.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.2.xsd">

    <!-- <security:http>: spring 过滤器链配置:
        1)需要拦截什么资源
        2)什么资源什么角色权限
        3)定义认证方式:HttpBasic,FormLogin(*)
        4)定义登录页面,定义登录请求地址,定义错误处理方式
    -->
    <security:http>
        <!--
            pattern: 需要拦截资源
            access: 拦截方式
                isFullyAuthenticated(): 该资源需要认证才可以访问
                isAnonymous():只有匿名用户才可以访问(如果登录用户就无法访问)
                permitAll():允许所有人(匿名和登录用户)访问
        -->
        <security:intercept-url pattern="/product/index" access="permitAll()"/>
        <!-- 自定义登录界面-->
        <security:intercept-url pattern="/userLogin.jsp" access="permitAll()"/>
        <security:intercept-url pattern="/**" access="isFullyAuthenticated()"/>
        
        <!--
            login-page: 自定义登录页面,默认为/login
            login-processing-url:登录请求拦截的url,也就是form表单提交时指定的action
            default-target-url 默认登录成功后跳转的url
            always-use-default-target 是否总是使用默认的登录成功后跳转url
            authentication-failure-url 登录失败后跳转的url
            username-parameter 用户名的请求字段 默认为userName
            password-parameter 密码的请求字段 默认为password
            authentication-success-handler-ref 指向一个AuthenticationSuccessHandler用于处理认证成功的请求,不能和default-target-url还有always-use-default-target同时使用
            authentication-success-forward-url 用于authentication-failure-handler-ref
            authentication-failure-handler-ref 指向一个AuthenticationFailureHandler用于处理失败的认证请求
            authentication-failure-forward-url 用于authentication-failure-handler-ref
            authentication-details-source-ref 指向一个AuthenticationDetailsSource,在认证过滤器中使用
        -->
        <security:form-login login-page="/userLogin.jsp"
                             login-processing-url="/login"
                             default-target-url="/jsp/index.jsp"
                             username-parameter="username"	<!-- 表示登录时用户名使用的是哪个参数 -->
                             password-parameter="password"	<!-- 表示登录时密码使用的是哪个参数 -->
                             />	

        <!-- 关闭 Spring Security CSRF 机制 -->
        <security:csrf disabled="true"/>

    </security:http>

    <!--
        security:authentication-manager: 认证管理器
        1)认证信息提供方式(账户名,密码,当前用户权限)
    -->
    <security:authentication-manager>
        <security:authentication-provider>
            <security:user-service>
                <security:user name="user" password="user" authorities="ROLE_USER"/>
            </security:user-service>
        </security:authentication-provider>
    </security:authentication-manager>
</beans>

3. 通过 < security:user-service > 配置实现用户权限访问控制

<?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-4.2.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.2.xsd">

    <!-- <security:http>: spring 过滤器链配置:
        1)需要拦截什么资源
        2)什么资源什么角色权限
        3)定义认证方式:HttpBasic,FormLogin(*)
        4)定义登录页面,定义登录请求地址,定义错误处理方式
    -->
    <security:http>
        <!--
            pattern: 需要拦截资源
            access: 拦截方式
                isFullyAuthenticated(): 该资源需要认证才可以访问
                isAnonymous():只有匿名用户才可以访问(如果登录用户就无法访问)
                permitAll():允许所有人(匿名和登录用户)访问
        -->
        <security:intercept-url pattern="/product/index" access="permitAll()"/>
        <!-- 自定义登录界面-->
        <security:intercept-url pattern="/userLogin.jsp" access="permitAll()"/>
		
		<!-- 定义每个资源的访问权限 -->
        <security:intercept-url pattern="/product/add" access="hasRole('ROLE_USER')"/>
        <security:intercept-url pattern="/product/update" access="hasRole('ROLE_USER')"/>
        <security:intercept-url pattern="/product/list" access="hasRole('ROLE_ADMIN')"/>
        <security:intercept-url pattern="/product/delete" access="hasRole('ROLE_ADMIN')"/>

        <security:intercept-url pattern="/**" access="isFullyAuthenticated()"/>

        <!-- security:http-basic: 使用 HttpBasic 方式进行登录(认证) -->
        <!--<security:http-basic/>-->

        <!-- security:form-login: 使用 FormLogin 方式进行登录(认证) -->
        <!--<security:form-login/>-->

        <!--
            login-page: 自定义登录页面,默认为/login
            login-processing-url:登录请求拦截的url,也就是form表单提交时指定的action
            default-target-url 默认登录成功后跳转的url
            always-use-default-target 是否总是使用默认的登录成功后跳转url
            authentication-failure-url 登录失败后跳转的url
            username-parameter 用户名的请求字段 默认为userName
            password-parameter 密码的请求字段 默认为password
            authentication-success-handler-ref 指向一个AuthenticationSuccessHandler用于处理认证成功的请求,不能和default-target-url还有always-use-default-target同时使用
            authentication-success-forward-url 用于authentication-failure-handler-ref
            authentication-failure-handler-ref 指向一个AuthenticationFailureHandler用于处理失败的认证请求
            authentication-failure-forward-url 用于authentication-failure-handler-ref
            authentication-details-source-ref 指向一个AuthenticationDetailsSource,在认证过滤器中使用
        -->
        <security:form-login login-page="/userLogin.jsp"
                             login-processing-url="/login"
                             default-target-url="/jsp/index.jsp"
                             username-parameter="username"
                             password-parameter="password"/>

        <!-- 自定义权限不足处理 -->
        <security:access-denied-handler error-page="/error.jsp"/>

        <!-- 关闭 Spring Security CSRF 机制 -->
        <security:csrf disabled="true"/>

    </security:http>

    <!--
        security:authentication-manager: 认证管理器
        1)认证信息提供方式(账户名,密码,当前用户权限)
    -->
    <security:authentication-manager>
        <security:authentication-provider>
            <security:user-service>
            	<!-- 两种认证身份 -->
                <security:user name="user" password="user" authorities="ROLE_USER"/>
                <security:user name="admin" password="admin" authorities="ROLE_ADMIN"/>
            </security:user-service>
        </security:authentication-provider>
    </security:authentication-manager>
</beans>

4. 自定义 UserDetailService接口实现类实现用户权限访问控制

关键:使用 UserDetailService 接口

1. 开发UserDetailService接口实现类

package com.example.config;

import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

public class MyUserDetailService implements UserDetailsService {
    /**
     * loadUserByUsername: 读取用户信息
     * @param username
     * @return
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //UserDetails: 封装用户数据的接口
        User user = new User( "user","user", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
        return user;
    }
}

其中 User 类就是 UserDetail 实现类,用于封装数据库账户信息

2. 配置spring-security.xml文件

加入如下配置:

	......
	
	<!-- 通过user-service-ref="myUserDetailService"的配置,使用UserDetailService接口实现类实现权限控制 -->
    <security:authentication-provider user-service-ref="myUserDetailService">
        
	......
	
    <!-- 将自定义的UserDetailService接口实现类MyUserDetailService注入spring容器 -->
    <bean id="myUserDetailService" class="com.example.config.MyUserDetailService"/>
    
    ......
    

完整的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-4.2.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.2.xsd">

    <!-- <security:http>: spring 过滤器链配置:
        1)需要拦截什么资源
        2)什么资源什么角色权限
        3)定义认证方式:HttpBasic,FormLogin(*)
        4)定义登录页面,定义登录请求地址,定义错误处理方式
    -->
    <security:http>
        <!--
            pattern: 需要拦截资源
            access: 拦截方式
                isFullyAuthenticated(): 该资源需要认证才可以访问
                isAnonymous():只有匿名用户才可以访问(如果登录用户就无法访问)
                permitAll():允许所有人(匿名和登录用户)访问
        -->
        <security:intercept-url pattern="/product/index" access="permitAll()"/>
        <!-- 自定义登录界面-->
        <security:intercept-url pattern="/userLogin.jsp" access="permitAll()"/>

        <security:intercept-url pattern="/product/add" access="hasRole('ROLE_USER')"/>
        <security:intercept-url pattern="/product/update" access="hasRole('ROLE_USER')"/>
        <security:intercept-url pattern="/product/list" access="hasRole('ROLE_ADMIN')"/>
        <security:intercept-url pattern="/product/delete" access="hasRole('ROLE_ADMIN')"/>

        <security:intercept-url pattern="/**" access="isFullyAuthenticated()"/>

        <!-- security:http-basic: 使用 HttpBasic 方式进行登录(认证) -->
        <!--<security:http-basic/>-->

        <!-- security:form-login: 使用 FormLogin 方式进行登录(认证) -->
        <!--<security:form-login/>-->

        <!--
            login-page: 自定义登录页面,默认为/login
            login-processing-url:登录请求拦截的url,也就是form表单提交时指定的action
            default-target-url 默认登录成功后跳转的url
            always-use-default-target 是否总是使用默认的登录成功后跳转url
            authentication-failure-url 登录失败后跳转的url
            username-parameter 用户名的请求字段 默认为userName
            password-parameter 密码的请求字段 默认为password
            authentication-success-handler-ref 指向一个AuthenticationSuccessHandler用于处理认证成功的请求,不能和default-target-url还有always-use-default-target同时使用
            authentication-success-forward-url 用于authentication-failure-handler-ref
            authentication-failure-handler-ref 指向一个AuthenticationFailureHandler用于处理失败的认证请求
            authentication-failure-forward-url 用于authentication-failure-handler-ref
            authentication-details-source-ref 指向一个AuthenticationDetailsSource,在认证过滤器中使用
        -->
        <security:form-login login-page="/userLogin.jsp"
                             login-processing-url="/login"
                             default-target-url="/jsp/index.jsp"
                             username-parameter="username"
                             password-parameter="password"/>

        <!-- 自定义权限不足处理 -->
        <security:access-denied-handler error-page="/error.jsp"/>

        <!-- 关闭 Spring Security CSRF 机制 -->
        <security:csrf disabled="true"/>

    </security:http>

    <!--
        security:authentication-manager: 认证管理器
        1)认证信息提供方式(账户名,密码,当前用户权限)
    -->
    <security:authentication-manager>
    	
    	<!-- 通过user-service-ref="myUserDetailService"的配置,使用UserDetailService接口实现类实现权限控制 -->
        <security:authentication-provider user-service-ref="myUserDetailService">
        
            <!--<security:user-service>-->
                <!--<security:user name="user" password="user" authorities="ROLE_USER"/>-->
                <!--<security:user name="admin" password="admin" authorities="ROLE_ADMIN"/>-->
            <!--</security:user-service>-->
        </security:authentication-provider>
    </security:authentication-manager>

    <!-- 将自定义的UserDetailService接口实现类MyUserDetailService注入spring容器 -->
    <bean id="myUserDetailService" class="com.example.config.MyUserDetailService"/>
    
</beans>

5. 自定义登录成功与失败处理逻辑

关键:
1)登录成功处理:AuthenticationSuccessHandler接口
2)登录失败处理:AuthenticationFailureHandler接口

1. 自定义登录成功处理逻辑

1. 引入jackson依赖

修改pom.xml文件

<!-- jackson 依赖 -->
    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.8</version>
    </dependency>

2. 开发AuthenticationSuccessHandler接口实现类

package com.example.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    //ObjectMapper: jackson 框架的工具类,用于转换对象为 json 字符串
    private ObjectMapper objectMapper = new ObjectMapper();
    /**
     * @param request
     * @param response
     * @param authentication :代表认证成功后的信息
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        //返回 json 字符串给前端
        Map result = new HashMap();
        result.put("succcess",true);

        String json = objectMapper.writeValueAsString(result);
        response.setContentType("text/json;charset=utf-8");
        response.getWriter().write(json);
    }
}

3. 配置spring-security.xml文件

加入如下配置:

	......
	
	<security:form-login 
		...... 其他属性配置
        authentication-success-handler-ref="myAuthenticationSuccessHandler"
        />
        
	......
	
	<!-- 将自定义的AuthenticationSuccessHandler接口实现类MyAuthenticationSuccessHandler注入spring容器 -->
    <bean id="myAuthenticationSuccessHandler" class="com.example.config.MyAuthenticationSuccessHandler"/>
    
    ......
    

完整的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-4.2.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.2.xsd">

    <!-- <security:http>: spring 过滤器链配置:
        1)需要拦截什么资源
        2)什么资源什么角色权限
        3)定义认证方式:HttpBasic,FormLogin(*)
        4)定义登录页面,定义登录请求地址,定义错误处理方式
    -->
    <security:http>
        <!--
            pattern: 需要拦截资源
            access: 拦截方式
                isFullyAuthenticated(): 该资源需要认证才可以访问
                isAnonymous():只有匿名用户才可以访问(如果登录用户就无法访问)
                permitAll():允许所有人(匿名和登录用户)访问
        -->
        <security:intercept-url pattern="/product/index" access="permitAll()"/>
        <!-- 自定义登录界面-->
        <security:intercept-url pattern="/userLogin.jsp" access="permitAll()"/>

        <security:intercept-url pattern="/product/add" access="hasRole('ROLE_USER')"/>
        <security:intercept-url pattern="/product/update" access="hasRole('ROLE_USER')"/>
        <security:intercept-url pattern="/product/list" access="hasRole('ROLE_ADMIN')"/>
        <security:intercept-url pattern="/product/delete" access="hasRole('ROLE_ADMIN')"/>

        <security:intercept-url pattern="/**" access="isFullyAuthenticated()"/>

        <!-- security:http-basic: 使用 HttpBasic 方式进行登录(认证) -->
        <!--<security:http-basic/>-->

        <!-- security:form-login: 使用 FormLogin 方式进行登录(认证) -->
        <!--<security:form-login/>-->

        <!--
            login-page: 自定义登录页面,默认为/login
            login-processing-url:登录请求拦截的url,也就是form表单提交时指定的action
            default-target-url 默认登录成功后跳转的url
            always-use-default-target 是否总是使用默认的登录成功后跳转url
            authentication-failure-url 登录失败后跳转的url
            username-parameter 用户名的请求字段 默认为userName
            password-parameter 密码的请求字段 默认为password
            authentication-success-handler-ref 指向一个AuthenticationSuccessHandler用于处理认证成功的请求,不能和default-target-url还有always-use-default-target同时使用
            authentication-success-forward-url 用于authentication-failure-handler-ref
            authentication-failure-handler-ref 指向一个AuthenticationFailureHandler用于处理失败的认证请求
            authentication-failure-forward-url 用于authentication-failure-handler-ref
            authentication-details-source-ref 指向一个AuthenticationDetailsSource,在认证过滤器中使用
        -->
        <security:form-login login-page="/userLogin.jsp"
                             login-processing-url="/login"
                             default-target-url="/jsp/index.jsp"
                             username-parameter="username"
                             password-parameter="password"
                             authentication-success-handler-ref="myAuthenticationSuccessHandler"
        />

        <!-- 自定义权限不足处理 -->
        <security:access-denied-handler error-page="/error.jsp"/>

        <!-- 关闭 Spring Security CSRF 机制 -->
        <security:csrf disabled="true"/>

    </security:http>

    <!--
        security:authentication-manager: 认证管理器
        1)认证信息提供方式(账户名,密码,当前用户权限)
    -->
    <security:authentication-manager>

        <!-- 通过user-service-ref="myUserDetailService"的配置,使用UserDetailService接口实现类实现权限控制 -->
        <security:authentication-provider user-service-ref="myUserDetailService">
            <!--<security:user-service>-->
                <!--<security:user name="user" password="user" authorities="ROLE_USER"/>-->
                <!--<security:user name="admin" password="admin" authorities="ROLE_ADMIN"/>-->
            <!--</security:user-service>-->
        </security:authentication-provider>
    </security:authentication-manager>

    <!-- 将自定义的UserDetailService接口实现类MyUserDetailService注入spring容器 -->
    <bean id="myUserDetailService" class="com.example.config.MyUserDetailService"/>

    <!-- 将自定义的AuthenticationSuccessHandler接口实现类MyAuthenticationSuccessHandler注入spring容器 -->
    <bean id="myAuthenticationSuccessHandler" class="com.example.config.MyAuthenticationSuccessHandler"/>

</beans>

2. 自定义登录失败处理逻辑

1. 引入jackson依赖

修改pom.xml文件

<!-- jackson 依赖 -->
    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.8</version>
    </dependency>

2. 开发AuthenticationSuccessHandler接口实现类

package com.example.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {

    //ObjectMapper: jackson 框架的工具类,用于转换对象为 json 字符串
    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
        //返回 json 字符串给前端
        Map result = new HashMap();
        result.put("succcess",false);
        String json = objectMapper.writeValueAsString(result);
        response.setContentType("text/json;charset=utf-8");
        response.getWriter().write(json);
    }
}

3. 配置spring-security.xml文件

加入如下配置:

	......
	
	<security:form-login 
		...... 其他属性配置
        authentication-failure-handler-ref="myAuthenticationFailureHandler"
        />
        
	......
	
    <!-- 将自定义的AuthenticationFailureHandler接口实现类MyAuthenticationFailureHandler注入spring容器 -->
    <bean id="myAuthenticationFailureHandler" class="com.example.config.MyAuthenticationFailureHandler"/>
    
    ......
    

完整的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-4.2.xsd
    http://www.springframework.org/schema/security
    http://www.springframework.org/schema/security/spring-security-4.2.xsd">

    <!-- <security:http>: spring 过滤器链配置:
        1)需要拦截什么资源
        2)什么资源什么角色权限
        3)定义认证方式:HttpBasic,FormLogin(*)
        4)定义登录页面,定义登录请求地址,定义错误处理方式
    -->
    <security:http>
        <!--
            pattern: 需要拦截资源
            access: 拦截方式
                isFullyAuthenticated(): 该资源需要认证才可以访问
                isAnonymous():只有匿名用户才可以访问(如果登录用户就无法访问)
                permitAll():允许所有人(匿名和登录用户)访问
        -->
        <security:intercept-url pattern="/product/index" access="permitAll()"/>
        <!-- 自定义登录界面-->
        <security:intercept-url pattern="/userLogin.jsp" access="permitAll()"/>

        <security:intercept-url pattern="/product/add" access="hasRole('ROLE_USER')"/>
        <security:intercept-url pattern="/product/update" access="hasRole('ROLE_USER')"/>
        <security:intercept-url pattern="/product/list" access="hasRole('ROLE_ADMIN')"/>
        <security:intercept-url pattern="/product/delete" access="hasRole('ROLE_ADMIN')"/>

        <security:intercept-url pattern="/**" access="isFullyAuthenticated()"/>

        <!-- security:http-basic: 使用 HttpBasic 方式进行登录(认证) -->
        <!--<security:http-basic/>-->

        <!-- security:form-login: 使用 FormLogin 方式进行登录(认证) -->
        <!--<security:form-login/>-->

        <!--
            login-page: 自定义登录页面,默认为/login
            login-processing-url:登录请求拦截的url,也就是form表单提交时指定的action
            default-target-url 默认登录成功后跳转的url
            always-use-default-target 是否总是使用默认的登录成功后跳转url
            authentication-failure-url 登录失败后跳转的url
            username-parameter 用户名的请求字段 默认为userName
            password-parameter 密码的请求字段 默认为password
            authentication-success-handler-ref 指向一个AuthenticationSuccessHandler用于处理认证成功的请求,不能和default-target-url还有always-use-default-target同时使用
            authentication-success-forward-url 用于authentication-failure-handler-ref
            authentication-failure-handler-ref 指向一个AuthenticationFailureHandler用于处理失败的认证请求
            authentication-failure-forward-url 用于authentication-failure-handler-ref
            authentication-details-source-ref 指向一个AuthenticationDetailsSource,在认证过滤器中使用
        -->
        <security:form-login login-page="/userLogin.jsp"
                             login-processing-url="/login"
                             default-target-url="/jsp/index.jsp"
                             username-parameter="username"
                             password-parameter="password"
                             authentication-success-handler-ref="myAuthenticationSuccessHandler"
                             authentication-failure-handler-ref="myAuthenticationFailureHandler"
        />

        <!-- 自定义权限不足处理 -->
        <security:access-denied-handler error-page="/error.jsp"/>

        <!-- 关闭 Spring Security CSRF 机制 -->
        <security:csrf disabled="true"/>

    </security:http>

    <!--
        security:authentication-manager: 认证管理器
        1)认证信息提供方式(账户名,密码,当前用户权限)
    -->
    <security:authentication-manager>

        <!-- 通过user-service-ref="myUserDetailService"的配置,使用UserDetailService接口实现类实现权限控制 -->
        <security:authentication-provider user-service-ref="myUserDetailService">
            <!--<security:user-service>-->
                <!--<security:user name="user" password="user" authorities="ROLE_USER"/>-->
                <!--<security:user name="admin" password="admin" authorities="ROLE_ADMIN"/>-->
            <!--</security:user-service>-->
        </security:authentication-provider>
    </security:authentication-manager>

    <!-- 将自定义的UserDetailService接口实现类MyUserDetailService注入spring容器 -->
    <bean id="myUserDetailService" class="com.example.config.MyUserDetailService"/>

    <!-- 将自定义的AuthenticationSuccessHandler接口实现类MyAuthenticationSuccessHandler注入spring容器 -->
    <bean id="myAuthenticationSuccessHandler" class="com.example.config.MyAuthenticationSuccessHandler"/>

    <!-- 将自定义的AuthenticationFailureHandler接口实现类MyAuthenticationFailureHandler注入spring容器 -->
    <bean id="myAuthenticationFailureHandler" class="com.example.config.MyAuthenticationFailureHandler"/>

</beans>

Spring Securit学习笔记之SS环境入门开发

6. Spring Security认证登录源码流程

参考:https://blog.****.net/abcwanglinyong/article/details/80981389

Spring Securit学习笔记之SS环境入门开发