SpringSecurity web

安全管理框架

需要依赖多

shiro 轻量

  • SSM+Shiro
  • SpringBoot/SpringCloud+SpringSecurity

配置用户名密码

  • 配置文件

  • extends WebSecurityConfigurerAdapter
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String password = passwordEncoder.encode("123");
auth.inMemoryAuthentication().withUser("lucy").password(password).roles("admin");
} @Bean
PasswordEncoder password() {
return new BCryptPasswordEncoder();
} }
  • 自定义实现类配置
  1. 创建配置类,设置使用哪个userDetailsService实现类
  2. 编写实现类,返回User对象,User对象有用户名密码和操作权限
  3. 自定义登录页面
@Configuration
public class SecurityConfig1 extends WebSecurityConfigurerAdapter { @Autowired
private UserDetailsService userDetailsService; @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(password());
} @Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()//自定义登录页面
.loginPage("/login.html") //登录页面
.loginProcessingUrl("/user/login") //登录访问路径
.defaultSuccessUrl("/test/index").permitAll() //登录成功跳转
.and().authorizeRequests()
.antMatchers("/","/test/add","/user/login").permitAll()
.anyRequest().authenticated()
.and().csrf().disable();//关闭csrf防护
} @Bean
PasswordEncoder password() {
return new BCryptPasswordEncoder();
} }
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService { @Autowired
private UsersMapper usersMapper; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
QueryWrapper<Users> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username",username);
Users users = usersMapper.selectOne(queryWrapper);
if(users == null ){
throw new UsernameNotFoundException("用户名不存在");
} //查数据库
List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("role"); // return new User(users.getUsername(),new BCryptPasswordEncoder().encode(users.getPassword()),auths);
}
}

设置访问权限

.antMatchers("/test/index").hasAuthority("admins")//只有admin权限才能访问

.antMatchers("/test/index").hasAnyAuthority("admins,manager")//有其中一个权限即可访问

.antMatchers("/test/index").hasRole("sale")//为ROLE_sale

.antMatchers("/test/index").hasAnyRole("sale,customer")//多个角色的任何一个就可访问

//配置没有权限访问跳转自定义页面
http.exceptionHandling().accessDeniedPage("/unauth.html");
    @Override
protected void configure(HttpSecurity http) throws Exception {
//配置没有权限访问跳转自定义页面
http.exceptionHandling().accessDeniedPage("/unauth.html"); http.formLogin()//自定义登录页面
.loginPage("/login.html") //登录页面
.loginProcessingUrl("/user/login") //登录访问路径
.defaultSuccessUrl("/test/index").permitAll() //登录成功跳转
.and().authorizeRequests()
.antMatchers("/","/test/add","/user/login").permitAll()
.antMatchers("/test/index").hasAuthority("admins")//只有admin权限才能访问
.anyRequest().authenticated()
.and().csrf().disable();//关闭csrf防护
}

注解授权

启动类上加注解

@EnableGlobalMethodSecurity(securedEnabled = true)

@SpringBootApplication
@EnableGlobalMethodSecurity(securedEnabled = true)
public class Springsecuritydemo1Application { public static void main(String[] args) {
SpringApplication.run(Springsecuritydemo1Application.class, args);
} }

@Secured

具有某个角色可以用访问该方法

@GetMapping("update")
@Secured({"ROLE_sale","ROLE_manager"})
public String update() {
return "hello update";
}

@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)

@PreAuthorize

执行方法前校验admins

@GetMapping("update")
//@Secured({"ROLE_sale","ROLE_manager"})
@PreAuthorize("hasAnyAuthority('admins')")
public String update() {
return "hello update";
}

@PostAuthorize

执行方法后校验

@PreFilter

@PostFilter

用户注销

修改配置类protected void configure(HttpSecurity http) throws Exception加上

http.logout().logoutUrl("/logout").logoutSuccessUrl("/index/add").permitAll();

自动登录

  1. Cookie
  2. 安全框架机制实现自动登录

原理:

  1. 认证成功->浏览器cookie存加密字符串,数据库存cookie的加密串,用户信息字符串
  2. 再次访问->获取cookie信息,拿着cookie信息到数据库进行比对,如果查询到对应信息,认证成功,就可以登录。

springsecurity实现:

  • 创建表
CREATE TABLE `persistent_logins`(
`username` VARCHAR (64) NOT NULL,
`series` VARCHAR(64) NOT NULL,
`token` VARCHAR(64) NOT NULL,
`last_used` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY(`series`)
)ENGINE=INNODB DEFAULT CHARSET=utf8;
  • 配置类注入数据源,配置操作数据库对象
    @Autowired
private DataSource dataSource; @Bean
public PersistentTokenRepository persistentTokenRepository(){
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
jdbcTokenRepository.setDataSource(dataSource); //jdbcTokenRepository.setCreateTableOnStartup(true); //设置自动创建token表
return jdbcTokenRepository;
}
  • .and().rememberMe().tokenRepository(persistentTokenRepository())
    .tokenValiditySeconds(60)//设置有效时长
    .userDetailsService(userDetailsService)//设置userDetailsService操作数据库
    @Override
protected void configure(HttpSecurity http) throws Exception { //配置没有权限访问跳转自定义页面
http.exceptionHandling().accessDeniedPage("/unauth.html"); //
http.logout().logoutUrl("/logout").logoutSuccessUrl("/test/add").permitAll(); http.formLogin()//自定义登录页面
.loginPage("/login.html") //登录页面
.loginProcessingUrl("/user/login") //登录访问路径
.defaultSuccessUrl("/success.html").permitAll() //登录成功跳转
.and().authorizeRequests()
.antMatchers("/","/test/add","/user/login").permitAll()
// .antMatchers("/test/index").hasAuthority("admins")//只有admin权限才能访问
// .antMatchers("/test/index").hasAnyAuthority("admins,manager")
//ROLE_xxx
.antMatchers("/test/index").hasRole("sale")
// .anyRequest().authenticated()
.and().rememberMe().tokenRepository(persistentTokenRepository())
.tokenValiditySeconds(60)//设置有效时长
.userDetailsService(userDetailsService)//设置userDetailsService操作数据库
.and().csrf().disable();//关闭csrf防护
}
  • 登录页面添加复选框 name必须为"remember-me"
<input type="checkbox" name="remember-me">自动登录

CSRF

跨站请求伪造

跨站请求攻击,简单地说,是攻击者通过一些技术手段七篇用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行

->>web中用户身份验证的一个漏洞:简单的身份验证之恶能保证请求发自某个用户的浏览器,却不能保证请求本身是用户自愿发出的。

实现CSRF原理:(只对"GET","HEAD","TRACE","OPTIONS"防护)

生成csrfToken保存到HttpSession,每次访问把带着过来的token和session存储的token是否一样

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
request.setAttribute(HttpServletResponse.class.getName(), response);
CsrfToken csrfToken = this.tokenRepository.loadToken(request);//创建token
boolean missingToken = csrfToken == null;
if (missingToken) {
csrfToken = this.tokenRepository.generateToken(request);
this.tokenRepository.saveToken(csrfToken, request, response);
} request.setAttribute(CsrfToken.class.getName(), csrfToken);
request.setAttribute(csrfToken.getParameterName(), csrfToken);//得到表单传递过来的token
//requireCsrfProtectionMatcher指定了防护的请求方式
if (!this.requireCsrfProtectionMatcher.matches(request)) {
filterChain.doFilter(request, response);
} else {
String actualToken = request.getHeader(csrfToken.getHeaderName());
if (actualToken == null) {
actualToken = request.getParameter(csrfToken.getParameterName());
} if (!csrfToken.getToken().equals(actualToken)) {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Invalid CSRF token found for " + UrlUtils.buildFullRequestUrl(request));
} if (missingToken) {
this.accessDeniedHandler.handle(request, response, new MissingCsrfTokenException(actualToken));
} else {
this.accessDeniedHandler.handle(request, response, new InvalidCsrfTokenException(csrfToken, actualToken));
} } else {
filterChain.doFilter(request, response);
}
}
}

Spring Security微服务权限

基本概念

单点登录:一次登录其他模块能直接操作

  • 基于Session,那么Spring Security会对cookie里的sessionId进行解析,找到服务器存储的session信息,然后判断当前用户是否符合请求的要求
  • 如果是token,则是解析出token,然后将当前请求加入到SpringSecurity管理的权限信息中去

查出权限列表,存入到redis中,根据用户名生成token再放入到cookie中,在header放token,springsecurity从header获取token,从token获取用户名,根据用户名从redis获取权限列表。由springsecurity给当前与用户赋予权限,可以进行相应操作。

案例

创建工程

登录

添加角色

为角色分配菜单

添加用户分配角色

SpringSecurity基本使用的更多相关文章

  1. spring mvc 和spring security配置 spring-servlet.xml和spring-security.xml设置

    spring-servlet.xml配置 <?xml version="1.0" encoding="UTF-8"?> <beans xmln ...

  2. 【JavaWeb】Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(前言)

    一直希望能够搭建一个完整的,基础Web框架,方便日后接一些外快的时候,能够省时省力,终于花了一周的时间,把这个东西搞定了.特此写下此博客,一来是纪念,二来是希望能够为别人提供方便.顺带说一下,恩,组合 ...

  3. 【JavaWeb】SSM+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(六)

    Showings 我个人的项目,当前不断地在更新. 我希望做成一个好项目,同时,也是在锻炼自己的技术. 在项目中发现问题,学习知识,是比较可取的一条路子. 这样学习到的知识,虽然分散,但是都很实用,而 ...

  4. 【JavaWeb】Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(五)

    SpringSecurity(2) 好久没有写了,之前只写了一半,我是一边开发一边写Blog一边上班,所以真心没有那么多时间来维护Blog,项目已经开发到编写逻辑及页面部分了,框架基本上已经搭建好不会 ...

  5. 【JavaWeb】Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(四)

    SpringSecurity(1) 其实啊,这部分我是最不想写的,因为最麻烦的也是这部分,真的是非常非常的麻烦.关于SpringSecurity的配置,让我折腾了好半天,网上的配置方式一大把,但总有一 ...

  6. 【JavaWeb】Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(一)

    Spring+MyBatis 首先要搭建的是Spring+MyBatis的整合框架,毕竟Spring是整个Web框架的核心部位,而数据库操作是一切测试的基础嘛. 目录结构 ━java ┣ contro ...

  7. SSO单点登录Spring-Security & CAS使用手册

    1.1概述 1.1.1单点登录介绍 单点登录(Single Sign On , 简称 SSO )是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应用系统中,用户只需要登录一次就可 ...

  8. spring4.2.3+mybatis+spring-security配置文件

    1.web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi=&qu ...

  9. springmvc+spring-security+mybatis +redis +solar框架抽取

    参考文章:Spring MVC 3 深入总结: 第二章 Spring MVC入门 —— 跟开涛学SpringMVC 参考博客:http://www.cnblogs.com/liukemng/categ ...

  10. 安全框架 SpringSecurity 和 Shiro 对比

    突然再次很想理一下权限的事,但是实在不知道实际情况选哪个框架好,现在整理下网上的资料,做一下对比. 1.Spring-security 对spring 结合较好,如果项目用的springmvc ,使用 ...

随机推荐

  1. WPF双滑块控件以及强制捕获鼠标事件焦点

    效果 概述 最近有个小需求要用双滑块表示一个取值范围,于是就简单做了个用户控件,在此记录下. 使用矩形Rectangle表示范围,椭圆Ellipse表示滑块,使用Canvas控制滑块的左右移动. 椭圆 ...

  2. 岭回归和LASSO

    0.对于正则罚项的理解 1.岭回归(L2 ridge regression ) 是一种专用于共线性数据分析的有偏估计回归方法,实质上是一种改良的最小二乘估计法,通过放弃最小二乘法的无偏性,以损失部分信 ...

  3. 【跟着大佬学JavaScript】之节流

    前言 js的典型的场景 监听页面的scroll事件 拖拽事件 监听鼠标的 mousemove 事件 ... 这些事件会频繁触发会影响性能,如果使用节流,降低频次,保留了用户体验,又提升了执行速度,节省 ...

  4. Java.稀疏数组

    package array; public class demo06 { public static void main(String[] args) { //创建一个二维数组 11*11 int[] ...

  5. PaddleOCR系列(一)--环境搭建

    官方建议使用他们的docker镜像,所以我们按照他们建议的来. 环境搭建其实很简单,其实不需要在宿主机上配置cuda及cudnn,只需要保证宿主机上的cuda大于docker镜像中的就可以了. 所以我 ...

  6. C#/VB.NET 添加多行文本水印到Word文档

    一般情况下,在Word中添加文字水印仅支持添加一个文本字样的水印,但在复杂的办公环境中,由于对不同文档的设计要求,需要在Word文档中添加平铺水印效果,即文档中的水印文字以多行多列分布的形式存在.本文 ...

  7. Python 元类详解

    一.Type介绍 在Python中一切皆对象,类它也是对象,而元类其实就是用来创建类的对象(由于一切皆对象,所以元类其实也是一个对象). 先来看这几个例子: 例1: In [1]: type(12) ...

  8. Java异步记录日志-2022新项目

    一.业务场景 web项目开发中,经常会有的一个操作是记录请求日志,比如记录请求的IP地址,记录请求的路径,记录请求的参数等等. 每个系统都会根据自己的需要来记录一些请求相关的日志.一般会将记录的日志信 ...

  9. 【定时功能】消息的定时发送-基于RocketMQ

    一.功能介绍 要实现一个消息的定时发送功能,也就是让消息可以在某一天某一个时间具体节点进行发送.而我们公司的业务场景是类似短信的业务,而且数量不小,用户会进行号码.消息内容.定时发送时间等信息的提交. ...

  10. 使用Docker-compose来封装celery4.1+rabbitmq3.7服务,实现微服务架构

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_115 大家都知道,Celery是一个简单.灵活且可靠的,处理大量消息的分布式系统,在之前的一篇文章中:python3.7+Torn ...