前言引入当今市面上用于权限管理的流行的技术栈组合是
ssm+shrio
springcloud+springboot+springsecurity
这种搭配自然有其搭配的特点,由于springboot的自动注入配置原理,在创建项目时就自动注入管理springsecurity的过滤器容器(delegatingfilterproxy),而这个过滤器是整个springsercurity的核心。掌握着springsercurity整个权限认证过程,而springboot很香的帮你将其自动注入了,而用ssm
去整合security,将会耗用大量的配置文件,不易于开发,而security的微服务权限方案,更是能和cloud完美融合,于是security比shrio更强大,功能更齐全。
security的核心配置文件核心:class securityconfig extends websecurityconfigureradapter
继承了websecurityconfigureradapter后我们关注于configure方法对于在整个安全认证的过程进行相关的配置,当然在配置之前我们先简单了解一下流程
简单的看了整个权限认证的流程,很轻易的总结得出,springsecurity核心的就是以下几种配置项了
拦截器(interceptor)
过滤器(filter)
处理器(handler,异常处理器,登录成功处理器)
那我们就首先通过配置来完成认证过程吧!!!!
security的认证过程假设我们要实现一下的认证功能
1. 是登录请求我们需要先判断验证码是否正确(验证码过滤器,通过addfilerbefore实现前置拦截)
再判断用户名密码是否正确(使用自带的用户名密码过滤器,usernamepasswordauthenticationfilter)
配置异常处理器(handler)通过io流将异常信息写出
关于密码校验的流程:
usernamepasswordauthenticationfilter的密码校验规则是基于authenticationmanagerbuilder(认证管理器)下的 userdetailsservice里的规则进行验证的:
其中的核心方法:
1.public userdetails *loaduserbyusername(string username)
通过请求参数的用户名去数据库查询是否存在,存在则将其封装在userdetails里面,而验证过程是通过authenticationmanagerbuilder获取到userdetail里的username和password来校验的,
这样我们就可以通过
配置yaml文件设置账号密码
通过数据库结合userdetail来设置账号密码
(userdetailsservice中的方法,注意需要将userdetailsservice注入authenticationmanagerbuilder中)
@override public userdetails loaduserbyusername(string username) throws usernamenotfoundexception { sysuser sysuser = sysuserservice.getbyusername(username); if (sysuser == null) { throw new usernamenotfoundexception("用户名或密码不正确"); } // 注意匹配参数,前者是明文后者是暗纹 system.out.println("是否正确"+bcryptpasswordencoder.matches("111111",sysuser.getpassword())); return new accountuser(sysuser.getid(), sysuser.getusername(), sysuser.getpassword(), getuserauthority(sysuser.getid())); }
通过了这个验证后,过滤器放行,不通过就用自定义或者默认的处理器处理
核心配置文件:
package com.markerhub.config;import com.markerhub.security.*;import org.springframework.beans.factory.annotation.autowired;import org.springframework.context.annotation.bean;import org.springframework.context.annotation.configuration;import org.springframework.security.config.annotation.authentication.builders.authenticationmanagerbuilder;import org.springframework.security.config.annotation.method.configuration.enableglobalmethodsecurity;import org.springframework.security.config.annotation.web.builders.httpsecurity;import org.springframework.security.config.annotation.web.configuration.enablewebsecurity;import org.springframework.security.config.annotation.web.configuration.websecurityconfigureradapter;import org.springframework.security.config.http.sessioncreationpolicy;import org.springframework.security.crypto.bcrypt.bcryptpasswordencoder;import org.springframework.security.web.authentication.usernamepasswordauthenticationfilter;@configuration@enablewebsecurity@enableglobalmethodsecurity(prepostenabled = true)public class securityconfig extends websecurityconfigureradapter { @autowired loginfailurehandler loginfailurehandler; @autowired loginsuccesshandler loginsuccesshandler; @autowired captchafilter captchafilter; @autowired jwtauthenticationentrypoint jwtauthenticationentrypoint; @autowired jwtaccessdeniedhandler jwtaccessdeniedhandler; @autowired userdetailserviceimpl userdetailservice; @autowired jwtlogoutsuccesshandler jwtlogoutsuccesshandler; @bean jwtauthenticationfilter jwtauthenticationfilter() throws exception { jwtauthenticationfilter jwtauthenticationfilter = new jwtauthenticationfilter(authenticationmanager()); return jwtauthenticationfilter; } @bean bcryptpasswordencoder bcryptpasswordencoder() { return new bcryptpasswordencoder(); } private static final string[] url_whitelist = { "/login", "/logout", "/captcha", "/favicon.ico", }; protected void configure(httpsecurity http) throws exception { http.cors().and().csrf().disable() // 登录配置 .formlogin() .successhandler(loginsuccesshandler) .failurehandler(loginfailurehandler) .and() .logout() .logoutsuccesshandler(jwtlogoutsuccesshandler) // 禁用session .and() .sessionmanagement() .sessioncreationpolicy(sessioncreationpolicy.stateless) // 配置拦截规则 .and() .authorizerequests() .antmatchers(url_whitelist).permitall() .anyrequest().authenticated() // 异常处理器 .and() .exceptionhandling() .authenticationentrypoint(jwtauthenticationentrypoint) .accessdeniedhandler(jwtaccessdeniedhandler) // 配置自定义的过滤器 .and() .addfilter(jwtauthenticationfilter()) .addfilterbefore(captchafilter, usernamepasswordauthenticationfilter.class) ; } @override protected void configure(authenticationmanagerbuilder auth) throws exception { auth.userdetailsservice(userdetailservice); }}
2. 不是登录请求通过jwtffilter来查看是否为登录状态
使用redis整合时的注意事项本质上还是编写过滤器链:
在登录请求前添加过滤器
注意验证码存储在redis的失效时间,如果超过失效时间将会被验证码拦截器拦截下来
需要准备一个生成验证码的接口,存储在redis中
使用完验证码需要将其删除
// 校验验证码逻辑 private void validate(httpservletrequest httpservletrequest) { string code = httpservletrequest.getparameter("code"); string key = httpservletrequest.getparameter("token"); if (stringutils.isblank(code) || stringutils.isblank(key)) { system.out.println("验证码校验失败2"); throw new captchaexception("验证码错误"); } system.out.println("验证码:"+redisutil.hget(const.captcha_key, key)); if (!code.equals(redisutil.hget(const.captcha_key, key))) { system.out.println("验证码校验失败3"); throw new captchaexception("验证码错误"); } // 一次性使用 redisutil.hdel(const.captcha_key, key); }
以上就是springsecurity+redis认证过程是怎样的的详细内容。