1认证

认证:辨别用户是否本系统用户。

优势:1 提供多样式的加密方法

2 提供多样式的用户存储方式

3 使用者无需关注验证封装业务 只需要提供查询方法即可

4 多样式的认证方式

5 提供用户信息获取方式

可扩展的功能

1 记住我

2 邮箱验证

3 手机验证

4 验证码验证

配置详解

spring security统一实现WebSecurityConfigurerAdapter接口 按照以下需求添加以下配置 就可以整合成功

@Configuration
@EnableWebSecurity // 开启springsecurity过滤链 filter
@EnableGlobalMethodSecurity(prePostEnabled = true) // 开启注解方法级别权限控制
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {//实现输入是明文 存储到数据库为密文 写死即可@Beanpublic PasswordEncoder passwordEncoder() {// 明文+随机盐值》加密存储return new BCryptPasswordEncoder();}//用户验证的业务流程 也就是查询用户的业务代码@AutowiredUserDetailsService customUserDetailsService;/*** 认证管理器: 将上文查询用户是否存在的service按样式写入 修改service 其余写死 还有密码写死或存放内存中等方式 这里不讨论* 1. 认证信息(用户名,密码)* @param auth* @throws Exception*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {// 数据库存储的密码必须是加密后的也就是必须要有passwordEncoder,不然会报错:There is no PasswordEncoder mapped forauth.userDetailsService(customUserDetailsService);}//验证码配置@Autowiredprivate ImageCodeValidateFilter imageCodeValidateFilter;//当验证成功后可以返回json或者路径 但是现在基于前后台分离 大多数都是返回json AuthenticationSuccessHandler为成功后转为json的处理 按照本文配置即可@Autowiredprivate AuthenticationSuccessHandler customAuthenticationSuccessHandler;//当验证成功后可以返回json或者路径 但是现在基于前后台分离 大多数都是返回json AuthenticationFailureHandler为失败后转为json的处理 按照本文配置即可@Autowiredprivate AuthenticationFailureHandler customAuthenticationFailureHandler;//建立数据源@AutowiredDataSource dataSource;@Autowiredprivate InvalidSessionStrategy invalidSessionStrategy;/*** 当同个用户session数量超过指定值之后 ,会调用这个实现类*/@Autowiredprivate SessionInformationExpiredStrategy sessionInformationExpiredStrategy;/*** 持久化token* @return*/@Beanpublic JdbcTokenRepositoryImpl jdbcTokenRepository() {JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();jdbcTokenRepository.setDataSource(dataSource);// 是否启动项目时自动创建表,true自动创建
//        jdbcTokenRepository.setCreateTableOnStartup(true);return jdbcTokenRepository;}/*** 核心拦截器 当你认证成功之后 ,springsecurity它会重写向到你上一次请求上* 资源权限配置:* 1. 被拦截的资源* @param http* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {//调用验证码过滤器 下文会详细介绍http.addFilterBefore(imageCodeValidateFilter, UsernamePasswordAuthenticationFilter.class).formLogin() // 表单登录方式.loginPage("/login/page") //登录页的页面地址.loginProcessingUrl("/login/form") // 登录表单提交处理url, 默认是/login.usernameParameter("username") //默认的是 username.passwordParameter("password")  // 默认的是 password.successHandler(customAuthenticationSuccessHandler) //登录成功返回的json.failureHandler(customAuthenticationFailureHandler) //登录失败返回的json.and() //每个类型的配置 以.and()间隔 相当于;.authorizeRequests() // 授权请求.antMatchers("/login/page","/code/image","/mobile/page", "/code/mobile","/code/image","/code/mobile","/mobile/page").permitAll() // 放行/login/page不需要认证可访问 因为如果在调用验证接口时还需要权限 那么就没有入口了 所以一些不需要登录就能访问的接口在此配置// 此处是鉴权// 有 sys:user 权限的可以访问任意请求方式的/role.antMatchers("/user").hasAuthority("sys:user")// 有 sys:role 权限的可以访问 get方式的/role.antMatchers(HttpMethod.GET,"/role").hasAuthority("sys:role").antMatchers(HttpMethod.GET, "/permission")// ADMIN 注意角色会在前面加上前缀 ROLE_ , 也就是完整的是 ROLE_ADMIN, ROLE_ROOT.access("hasAuthority('sys:premission') or hasAnyRole('ADMIN', 'ROOT')")// 此处是鉴权.anyRequest().authenticated() //所有访问该应用的http请求都要通过身份认证才可以访问.and().rememberMe() //记住我功能//记住功能配置.tokenRepository(jdbcTokenRepository()) //保存token信息.tokenValiditySeconds(604800) //记住我有效时长.and().sessionManagement()// session管理.invalidSessionStrategy(invalidSessionStrategy) //当session失效后的处理类 //.expiredSessionStrategy(sessionInformationExpiredStrategy)// 当用户达到最大session数后,则调用此处的实现.maximumSessions(1) // 每个用户在系统中最多可以有多少个session.maxSessionsPreventsLogin(true) // 当一个用户达到最大session数,则不允许后面再登录.sessionRegistry(sessionRegistry()).and().and().logout()//登出相关.addLogoutHandler(customLogoutHandler) // 退出清除缓存.logoutUrl("/user/logout") // 退出请求路径.logoutSuccessUrl("/mobile/page") //退出成功后跳转地址.deleteCookies("JSESSIONID") // 退出后删除什么cookie值;// 注意不要少了分号http.csrf().disable(); // 关闭跨站请求伪造}/*** 退出清除缓存*/@Autowiredprivate CustomLogoutHandler customLogoutHandler;/*** 为了解决退出重新登录问题* @return*/@Beanpublic SessionRegistry sessionRegistry() {return new SessionRegistryImpl();}/*** 一般是针对静态资源放行* @param web* @throws Exception*/@Overridepublic void configure(WebSecurity web){web.ignoring().antMatchers("/js/**", "/css/**");}
}

清除缓存方法

@Component
public class CustomLogoutHandler implements LogoutHandler {@Autowiredprivate SessionRegistry sessionRegistry;@Overridepublic void logout(HttpServletRequest request,HttpServletResponse response,Authentication authentication) {// 退出之后 ,将对应session从缓存中清除 SessionRegistryImpl.principalssessionRegistry.removeSessionInformation(request.getSession().getId());}
}

编写user验证方法类

需要继承UserDetailsService  为jar包提供

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

获取SysUser实体方法和获取此人菜单的方法 这里不多说

public abstract class AbstractUserDetailsService implements UserDetailsService {@Autowiredprivate SysPermissionService sysPermissionService;/*** 这个方法交给子类去实现它,查询用户信息** @param usernameOrMobile 用户名或者手机号* @return*/public abstract SysUser findSysUser(String usernameOrMobile);@Overridepublic UserDetails loadUserByUsername(String usernameOrMobile) throws UsernameNotFoundException {// 1. 通过请求的用户名去数据库中查询用户信息SysUser sysUser = findSysUser(usernameOrMobile);// 通过用户id去获取权限信息findSysPermission(sysUser);return sysUser;}private void findSysPermission(SysUser sysUser) {if (sysUser == null) {throw new UsernameNotFoundException("用户名或密码错误");}// 2. 查询该用户有哪一些权限List<SysPermission> permissions = sysPermissionService.findByUserId(sysUser.getId());if (CollectionUtils.isEmpty(permissions)) {return;}// 在左侧菜单 动态渲染会使用,目前先把它都传入sysUser.setPermissions(permissions);// 3. 封装权限信息List<GrantedAuthority> authorities = Lists.newArrayList();for (SysPermission sp : permissions) {// 权限标识String code = sp.getCode();authorities.add(new SimpleGrantedAuthority(code));}sysUser.setAuthorities(authorities);}
}
@Component("customUserDetailsService")
public class CustomUserDetailsService extends AbstractUserDetailsService{Logger logger = LoggerFactory.getLogger(getClass());@Autowired // 不能删掉,不然报错PasswordEncoder passwordEncoder;@AutowiredSysUserService sysUserService;@Overridepublic SysUser findSysUser(String usernameOrMobile) {logger.info("请求认证的用户名: " + usernameOrMobile);// 1. 通过请求的用户名去数据库中查询用户信息return sysUserService.findByUsername(usernameOrMobile);}
}
CustomAuthenticationSuccessHandler与CustomAuthenticationFailureHandler
//此类没有注入,因为楼主并没有使用
@Component("customAuthenticationSuccessHandler")
public class CustomAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {@Autowired(required = false) // 容器中可以不需要有接口的实现,如果有则自动注入AuthenticationSuccessListener authenticationSuccessListener;@Overridepublic void onAuthenticationSuccess(HttpServletRequest request,HttpServletResponse response, Authentication authentication) throws IOException, ServletException {if(authenticationSuccessListener != null) {// 当认证之后 ,调用此监听,进行后续处理,比如加载用户权限菜单authenticationSuccessListener.successListener(request, response, authentication);}if(LoginResponseType.JSON.equals("post")) {// 认证成功后,响应JSON字符串MengxueguResult result = MengxueguResult.ok("认证成功");response.setContentType("application/json;charset=UTF-8");response.getWriter().write(result.toJsonString());}else {//重定向到上次请求的地址上,引发跳转到认证页面的地址logger.info("authentication: " + JSON.toJSONString(authentication));super.onAuthenticationSuccess(request, response, authentication);}}
}
@Component("customAuthenticationFailureHandler")
public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {/**** @param exception 认证失败时抛出异常*/@Overridepublic void onAuthenticationFailure(HttpServletRequest request,HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {if(LoginResponseType.JSON.equals("post")) {// 认证失败响应JSON字符串,MengxueguResult result = MengxueguResult.build(HttpStatus.UNAUTHORIZED.value(), exception.getMessage());response.setContentType("application/json;charset=UTF-8");response.getWriter().write(result.toJsonString());}else {// 重写向回认证页面,注意加上 ?error
//            super.setDefaultFailureUrl(securityProperties.getAuthentication().getLoginPage()+"?error");// 获取上一次请求路径String referer = request.getHeader("Referer");logger.info("referer:" + referer);// 如果下面有值,则认为是多端登录,直接返回一个登录地址Object toAuthentication = request.getAttribute("toAuthentication");String lastUrl = toAuthentication != null ? "/login/page": StringUtils.substringBefore(referer,"?");logger.info("上一次请求的路径 :" + lastUrl);super.setDefaultFailureUrl(lastUrl+"?error");super.onAuthenticationFailure(request, response, exception);}}
}

五分钟带你玩转SpringSecurity(四)配置全解析,带你掌握security核心要点相关推荐

  1. linux 查看防火墙状态_每天五分钟学习Linux系列之 - 系统安全配置

    20年IT从业,二哥的团队使用最多的系统就是Linux,开发,运维的小伙伴们都离不开Linux系统,特别是大数据和人工智能领域更是如此,但由于日常工作忙,小伙伴们没有太多成块的时间系统的学习Linux ...

  2. 带你玩转Visual Studio(八)——带你跳出坑爹的Runtime Library坑

    在Windows下进行C++的开发,不可避免的要与Windows的底层库进行交互,然而VS下的一项设置MT.MTd.MD和MDd却经常让人搞迷糊,相信不少人都被他坑过,特别是你工程使用了很多第三库的时 ...

  3. 【凯子哥带你学Framework】Activity界面显示全解析

    前几天凯子哥写的Framework层的解析文章<Activity启动过程全解析>,反响还不错,这说明"写让大家都能看懂的Framework解析文章"的思想是基本正确的. ...

  4. 五分钟了解GRE是什么,四信GRE相关应用推荐

    随着互联网新技术的发展以及智能化水平的提高,各企业对实时数据传输的需求也在不断提升,企业愈发重视数据中心的建设,各类虚拟网络技术相继被引入.今天,我们重点了解下云端"借道"鼻祖,善 ...

  5. 老司机带你玩转git (四) git的协同合作

    大家都知道,git被戏称为全球最大的同性的交友平台.在这里,不仅能完成各种项目的学习,更能完成各种姿势的学习(呜呜呜呜呜~小火车经过啦).那么为了更好的开车(学习).我想我们有必要学习pull req ...

  6. 老猪带你玩转自定义控件三——sai大神带我实现ios 8 时间滚轮控件

    ios 8 的时间滚轮控件实现了扁平化,带来很好用户体验,android没有现成控件,小弟不才,数学与算法知识不过关,顾十分苦恼,幸好在github上找到sai大神实现代码,甚为欣喜,顾把学习这个控件 ...

  7. 【五面阿里】现在分享一下阿里最全面试88题:阿里巴巴核心技术部、蚂蚁金服、天猫面试题含答案...

    貌似这一点适应的行业最广,但是我可以很肯定的说:当你从事Java一年后,重新找工作时,才会真实的感受到这句话. 工作第一年,往往是什么都充满新鲜感,什么都学习,冲劲十足的一年:WEB行业知识更新特别快 ...

  8. 手把手带你玩转Spark机器学习-使用Spark构建回归模型

    系列文章目录 手把手带你玩转Spark机器学习-专栏介绍 手把手带你玩转Spark机器学习-问题汇总 手把手带你玩转Spark机器学习-Spark的安装及使用 手把手带你玩转Spark机器学习-使用S ...

  9. 手把手带你玩转Spark机器学习-使用Spark进行数据处理和数据转换

    系列文章目录 手把手带你玩转Spark机器学习-专栏介绍 手把手带你玩转Spark机器学习-问题汇总 手把手带你玩转Spark机器学习-Spark的安装及使用 手把手带你玩转Spark机器学习-使用S ...

最新文章

  1. javascript优缺点_为什么要在JavaScript中使用静态类型? 优缺点
  2. 中国乒乓球,牛!!!!
  3. 存在于一维空间的稳定分子
  4. 表达提交返回信息_盘锦市2020年义务教育阶段招生入学信息服务平台家长填报指南...
  5. keil5改工程名称_修改Keil工程名称并添加其他模块文件
  6. 苹果的程序员三大定律
  7. local sandbox html里的script tag是如何load到memory里的
  8. css3实现科技感的呼吸灯效果
  9. mysql 外键和事务_Mysql (五)事务和外键
  10. php pdo query 空判断,检查空结果(php,pdo,mysql)
  11. 与人方便,随遇而安!
  12. java redis hscan_如何在Redis中使用HSCAN命令?
  13. jeesit 可以用俩种导出
  14. r语言调用python_如何在Rstudio中使用python 语言 (图文详解)
  15. 怎样将tiff格式转成jpg或png?
  16. 平台型时间信号强度曲线_MRI对动态增强时间信号曲线呈平台型乳腺纤维.PDF
  17. 我的2018---艰难的一年
  18. 域名网在线出售域名源码
  19. Locale 和 LanguageTag
  20. 网站如何报价 做一个普通企业网站多少钱?

热门文章

  1. N/A,NG,NV是什么意思
  2. ROS :Tranform出错简易处理 tf出错现象及解析
  3. 解决RDkit输入smiles画分子的二维图时出现保存不了图片的问题: AttributeError: ‘Image‘ object has no attribute ‘save‘
  4. 基于1DCNN(一维卷积神经网络)的目标识别
  5. MySQL+JAVA 员工考勤管理系统 数据库大作业
  6. Eclipse 注释xml 快捷键
  7. SQL中只要用到聚合函数就一定要用到group by 吗?
  8. 2019年压力焊作业安全生产模拟考试题库及答案
  9. sqlzoo练习答案
  10. 免除个人提供征信报告!卡尔数科究竟意欲何为?