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. 一文讲明白K8S各核心架构组件

    目录 一.写在前面 二.K8S为我们提供了怎样的能力 三.架构 3.1.MasterNode 3.2.WorkerNode 四.核心组件 4.1.ApiServer 4.1.1.概述 4.1.2.是集 ...

  2. Tapdata 数据库实时同步的技术要点

    Tapdata 是由深圳钛铂数据有限公司研发的一款实时数据处理及服务的平台产品,企业可以使用 Tapdata 快速构建数据中台和实时数仓, Tapdata 提供了一站式的解决方案,包括实时数据采集.数 ...

  3. 《吐血整理》保姆级系列教程-玩转Fiddler抓包教程(4)-会话面板和HTTP会话数据操作详解

    1.简介 按照从上往下,从左往右的计划,今天就轮到介绍和分享Fiddler的会话面板了. 2.会话列表 (Session list) 概览 Fiddler抓取到的每条http请求(每一条称为一个ses ...

  4. 如何优雅的升级 Flink Job?

    Flink 作为有状态计算的流批一体分布式计算引擎,会在运行过程中保存很多的「状态」数据,并依赖这些数据完成任务的 Failover 以及任务的重启恢复. 那么,请思考一个问题:如果程序升级迭代调整了 ...

  5. AtCoder Beginner Contest 260 F - Find 4-cycle

    题目传送门:F - Find 4-cycle (atcoder.jp) 题意: 给定一个无向图,其包含了S.T两个独立点集(即S.T内部间的任意两点之间不存在边),再给出图中的M条边(S中的点与T中的 ...

  6. mysql 01: source命令

    使用mysql的source命令,执行sql脚本 之所以使用docker同步挂载卷的方法,是因为在docker中运行的mysql未安装vim或gedit等基本编辑器 不方便在mysql容器里直接写sq ...

  7. vue-resource && axios

    1 # axios 2 # 1.安装:npm i axios 3 # 2.使用: 4 import axios from 'axios' 5 axios.get(URL).then(response= ...

  8. Mybatis的使用(4)

    1:解决实体类成员变量和数据库表中字段名称不一致的问题: 方法1:在写sql语句时,给表中的列名起别名,名字和实体类名称一样 方法2:使用resultMap来解决: 例如:实体类中成员变量为id,na ...

  9. 高考集训讲课(To 高一)

    高考集训讲课(To 高一) 主要是怕下午讲着讲着把自己讲懵了,有一定的迷糊概率 经过机房的讨论,一致认为插头\(DP\)实用性不大,所以这次不讲了,先把重要的讲一讲. 顺便吐槽一下,凭什么另外几个人都 ...

  10. ​在Docker中部署GreatSQL并构建MGR集群

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 为了方面社区用户体验GreatSQL,我们同时还提供Docker镜像,本文详细介绍如何在Docker中部署GreatSQL ...