Spring Security修炼手册(三)————Security个性化认证流程

Stella981
• 阅读 315

    在第二章节,我们主要学习了Security的自定义认证的实现和认证的流程,同时也存在一些问题,比如我们想在用户认证成功或失败后记录日志等相关操作,我们怎么办呢?别担心,Security已经为我们想好了,我们只需要实现其提供的接口并配置即可。

一、 自定义登录成功处理

    AuthenticationSuccessHandle是Security提供的认证成功处理器接口,代码如下:

Spring Security修炼手册(三)————Security个性化认证流程

    现在我们具体实现以下,比如我们在用户认证成功后,打印一段某某用户在什么时间登录成功的日志,并返回给前端页面当前用户的认证信息:

import java.io.IOException;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.databind.ObjectMapper;

@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
        
    private Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    private ObjectMapper objectMapper;
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
            Authentication authentication) throws IOException, ServletException {
        // TODO Auto-generated method stub
        logger.info(authentication.getName()+"在"+new Date()+"登录成功");
        response.setContentType("application/json;charset=UTF-8");
        response.getWriter().write(objectMapper.writeValueAsString(authentication));

    }

}

    然后我们需要将认证成功处理器在SecurityConfig中配置一下:

Spring Security修炼手册(三)————Security个性化认证流程

启动项目,再次登录,web界面显示如下:

Spring Security修炼手册(三)————Security个性化认证流程

     我们可以看到Authentication中有当前用户的权限、Session、名字等等信息,Authentication就是认证成功后Security为我们提供的一个封装,里面具体都有什么属性,感兴趣的朋友可以具体去看这个接口,这里不做详述。

        后台Log输出如下:

Spring Security修炼手册(三)————Security个性化认证流程

二、 自定义认证失败处理

        通过名字大家应该可以猜出Security提供的失败处理器的名字叫做:AuthenticationFailureHandler,

这个处理器和成功处理器还是有区别的,成功处理器方法中最后一个参数是封装好的用户认证信息,而失败处理器最后一个参数是在UserDetailServer中所捕获到的异常信息。可以看下我实现的逻辑:打印抛出的异常信息。

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;

@Component
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {

    private Logger logger = LoggerFactory.getLogger(getClass());
    /* (non-Javadoc)
     * @see org.springframework.security.web.authentication.AuthenticationFailureHandler#onAuthenticationFailure(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.springframework.security.core.AuthenticationException)
     */
    @Override
    public void onAuthenticationFailure(HttpServletRequest arg0, HttpServletResponse response, AuthenticationException authentication)
            throws IOException, ServletException {
        
        logger.info(authentication.getMessage()+"---登录失败");
        response.setHeader("content-type","text/html;charset=UTF-8");
        response.getWriter().println("<script>alert('"+ authentication.getMessage()+"');</script>");

    }

}

同样的在SecurityConfig中配置失败处理器,再次登录:

Spring Security修炼手册(三)————Security个性化认证流程

    可以看到打印出的异常信息为“坏的凭证”,实际上这个是Security中默认的异常信息,我们跑一遍源码,来看一看Security是怎么对比我们在表单输入的信息与UserDetailServer中(数据库)的对比,以及异常的处理的。

    任意输入用户名,密码,点击登录,我们还是先来到了UsernamePasswordAuthenticationFilter中。

Spring Security修炼手册(三)————Security个性化认证流程

我们继续往下走,一直走到我们的UserDetailServer的实现中。

Spring Security修炼手册(三)————Security个性化认证流程

    走到User的时候我们直接走进去,进入到DaoAuthenticationProvider,在这里会对User进行初步的检查,我们看右上角的堆栈信息,可以看到loadedUser中我画红框值为true的属性,实际上这几个是框架默认填充的值,这因为我们只调用了三个参数的构造器,如果我们调用七个参数的构造器,就可以根据我们自己的业务逻辑去进行true或false的判断,抛出相应的异常信息。

Spring Security修炼手册(三)————Security个性化认证流程

当我们继续走,下面就开始对User进行用户名,密码,是否可用等等各种检查,如果发现出现问题,则抛出异常信息。

Spring Security修炼手册(三)————Security个性化认证流程

由于我填写的密码是错误的,所以在检查过程中,抛出以下异常“坏的凭证”,认证是是失败的,那个false的含义是我是第一次经过认证的。

Spring Security修炼手册(三)————Security个性化认证流程

而这里抛出的异常信息“坏的凭证”则会被我们的失败处理器所捕获,这就是异常信息捕获的全部过程。

Spring Security修炼手册(三)————Security个性化认证流程

三、自定义异常信息

    第二节我们详细的讲解了异常信息的捕获流程,但是在我们的实际业务需求中,异常信息可能不是“坏的凭证”这样的字符串,如果我想自定义信息,怎么办呢?也很简单,请看代码:

    我将UserDetailServer稍作修改。

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;
import org.springframework.stereotype.Component;

@Component
public class MyUserDetailsServer implements UserDetailsService {

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // TODO Auto-generated method stub
        if("admin".equals(username)){
            
            throw new RuntimeException("admin禁止登录");
        }
        return new User(username, "$2a$10$ofPkBDUezOJp6Sik63Q/0.QlU8a1itEyzldjSXqfn2nDPqXjN0Ljm", AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
    }

}

我这里只是举一个例子,具体你们的业务需求是怎样的,自己实现就好。重启项目,使用admin登录,效果如下。

Spring Security修炼手册(三)————Security个性化认证流程

Spring Security修炼手册(三)————Security个性化认证流程

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
kenx kenx
2年前
轻松上手SpringBoot+SpringSecurity+JWT实RESTfulAPI权限控制实战
前言我们知道在项目开发中,后台开发权限认证是非常重要的,springboot中常用熟悉的权限认证框架有,shiro,还有就是springboot全家桶的security当然他们各有各的好处,但是我比较喜欢springboot自带的权限认证框架xmlorg.springframework.bootspr
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
九鹤 九鹤
3年前
security 概念
security创建核心配置文件java@EnableWebSecuritypublicclassSeurityConfigextendsWebSecurityConfigurerAdapter{}改写方法java/认证在内存中创建了一个用户
Stella981 Stella981
2年前
JWT验证机制【刘新宇】【Django REST framework中使用JWT】
JWT在用户注册或登录后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证。我们不再使用Session认证机制,而使用JsonWebToken认证机制。什么是JWTJsonwebtoken(JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC7519(https:/
Stella981 Stella981
2年前
CAS 5.3.1系列之自定义Shiro认证策略(四)
CAS5.3.1系列之自定义Shiro认证策略(四)CAS官方文档是介绍基于配置实现shiro认证的,可以参考官方文档,不过我们也可以通过自定义认证策略的方式实现jdbc认证,pom先加入相关jar<!CustomAuthentication<dependency
Wesley13 Wesley13
2年前
Asp.Net Forms认证在移动平台中遇到的一个问题以及调查过程
我们项目的网站的移动版是基于Asp.Net平台开发的,用户登录也是基于Asp.Net的Forms认证,在整个开发和测试过程中没有发现任何客户登录异常,但是发布后断断续续有用户反映在登录页面登录成功后跳转主页后,主页并没有识别登录用户,也即是Form认证失败。Asp.Net的Form认证大家应该有所了解,其内部的机制就是把用户数据加密后保存在一个基于cook
Stella981 Stella981
2年前
Django REST framework JWT学习
1.JWT学习在用户注册或登录后,我们想记录用户的登录状态,或者为用户创建身份认证的凭证。我们不再使用Session认证机制,而使用JsonWebToken认证机制。Jsonwebtoken(JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC7519).该token被设计为紧凑且安全的,
Stella981 Stella981
2年前
Spring Security修炼手册(二)————Security的认证流程
    那么通过第一节的介绍,大家对于Security认证的使用应该具备了一个基本的认识,那么这节主要有三个知识点。1、初步的带大家了解Security中几个过滤器(后面会一点点的加入其它过滤器)。2、表单认证的处理流程。3、如何自定义用户认证逻辑。那么废话不多说,直接进入第一点。   哦!对了,我还要补充一点,有很多小伙伴私信我说,怎么能在用户完成认
Stella981 Stella981
2年前
Spring Security修炼手册(四)————Security默认表达式的权限控制
       前三章主要讲的是Security对于认证的处理,那么本节,会为大家介绍基于Security默认表达式的权限控制(较为简单,无法满足复杂权限控制及多变的权限规则,后面会介绍基于自定义表达式的权限访问控制,可满足99%的业务场景的需求)。一、介绍及使用 直接进入主题,基于默认的表达式权限控制,需要在SecurityConf