springboot对security的后端配置
一、Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。
二、security和springboot也做了深度的契合,所以我们这里使用security来配置相关访问。因为项目可以做前后端的分理,我这里就不讲对于后台处理页面的配置了。这里主要是讲一些针对于纯后端开发,进行security的相关配置,当然只是其中一部分。
三、讲到的点主要有:跨域、认证、加密、权限控制等。
四、实现部分
1、pom.xml需要的依赖(这里只写主要部分,parent等自己按需要导入依赖)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
说明:说明一点,我这里使用的是2.0.0的版本,如何有需要可以自己根据不同的版本进行配置
2、主要的配置部分
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.web.filter.CorsFilter; @Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { //跨域
@Autowired
private CorsFilter corsFilter; //认证处理类
@Autowired
private DaoAuthenticationProvider daoAuthenticationProvider; //认证成功
@Autowired
private AuthenticationSuccessHandler successHandler; //认证失败
@Autowired
private AuthenticationFailureHandler failureHandler; //登出成功
@Autowired
private LogoutSuccessHandler logoutSuccessHandler; @Autowired
private AccessDeniedHandler deniedHandler; //认证EntryPoint
@Autowired
private AuthenticationEntryPoint entryPoint; @Override
protected void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.authenticationProvider(daoAuthenticationProvider);
} @Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(HttpMethod.OPTIONS, "/api/**")
.antMatchers("/swagger-ui.html")
.antMatchers("/webjars/**")
.antMatchers("/swagger-resources/**")
.antMatchers("/v2/**");
} @Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.addFilterBefore(corsFilter, CsrfFilter.class)
.exceptionHandling()
.authenticationEntryPoint(entryPoint)
.accessDeniedHandler(deniedHandler)
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/api/user/login")
.successHandler(successHandler)
.failureHandler(failureHandler)
.and()
.logout().logoutUrl("/api/user/logout")
.logoutSuccessHandler(logoutSuccessHandler)
.and()
.headers()
.frameOptions()
.disable()
.and()
.sessionManagement().maximumSessions(1800);
}
}
3、csrf防护
这个我这里不详细讲,主要的目的就是每次访问的时候除了带上自己的访问凭据以外,还需要带上每次csrf的票据。当然这个是会根据具体的会话进行变化的,也就是防止csrf攻击。
如果csrf放开配置方式可以为cookie
即:将.csrf().disable()换成.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
如果存在后端接口忽略的加入:.ignoringAntMatchers("/api/user/login")
访问的时候带上csrf的访问票据,携带方式为下面2种方式。票据的获取方式为第一次访问的时候回通过cookie的方式带入
request:_csrf:票据
header:X-XSRF-TOKEN:票据
4、跨域(配置方式见注入部分)
跨域问题我相信在使用前后台分理的时候肯定会出现这种问题,那么怎么样配置跨域问题呢!这里提供了一种方式(CorsFilter.class)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter; import java.util.ArrayList;
import java.util.List; @Configuration
public class CorsFilterConfiguration { @Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
List<String> allowedOrigins = new ArrayList<>();
allowedOrigins.add("*");
List<String> allowedMethods = new ArrayList<>();
allowedMethods.add("*");
List<String> allowedHeaders = new ArrayList<>();
allowedHeaders.add("*");
List<String> exposedHeaders = new ArrayList<>();
exposedHeaders.add("Link");
exposedHeaders.add("X-Total-Count");
corsConfiguration.setAllowedOrigins(allowedOrigins);
corsConfiguration.setAllowedMethods(allowedMethods);
corsConfiguration.setAllowedHeaders(allowedHeaders);
corsConfiguration.setExposedHeaders(exposedHeaders);
corsConfiguration.setAllowCredentials(true);
corsConfiguration.setMaxAge(1800L);
source.registerCorsConfiguration("/api/**", corsConfiguration);return new CorsFilter(source);
}
}
5、认证处理以及加密处理
这里的加密方式采用的是springsecurity提供的一种加密方式:BCryptPasswordEncoder(hash、同一密码加密不一样的密钥),认证配置见builder部分
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration
public class PasswordEncoderConfiguration { /**
* 密码加密
*/
@Bean
public BCryptPasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
import com.cetc.domain.Role;
import com.cetc.domain.User;
import com.cetc.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
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.Service;
import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList;
import java.util.List; @Service
@Transactional
public class AuthDetailsService implements UserDetailsService { @Autowired
private UserRepository userRepository; @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByUsername(username);
if (user == null){
throw new UsernameNotFoundException("用户不存在!");
}
List<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<>();
List<Role> roles = user.getRoles();
if (roles != null && !roles.isEmpty()) {
roles.stream().forEach(role -> simpleGrantedAuthorities.add(new SimpleGrantedAuthority(role.getRoleType())));
}
return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), simpleGrantedAuthorities);
}
}
说明:这里的UsernameNotFoundException如果是默认配置,是不能被处理类所捕获的。原因:DaoAuthenticationProvider父类AbstractUserDetailsAuthenticationProvider中hideUserNotFoundExceptions为true
解决方式重新配置:DaoAuthenticationProvider
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration
public class CustomDaoAuthenticationProvider { @Autowired
private AuthDetailsService authDetailsService; @Autowired
private BCryptPasswordEncoder passwordEncoder; @Bean
public DaoAuthenticationProvider daoAuthenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(authDetailsService);
provider.setPasswordEncoder(passwordEncoder);
provider.setHideUserNotFoundExceptions(false);
return provider;
}
}
然后修改builder.userDetailsService(authDetailsService).passwordEncoder(passwordEncoder);为builder.authenticationProvider(provider);
这种方式就可以解决异常包装的问题了,这里我们是采用的原生的配置方式。
6、各个切入点(AuthenticationEntryPoint、AccessDeniedHandler、AuthenticationSuccessHandler、AuthenticationFailureHandler、LogoutSuccessHandler)五个切入点,作用就是在对应操作过后,可以根据具体的切入点进行相应异常的处理
import com.alibaba.fastjson.JSONObject;
import com.cetc.constant.SystemErrorCode;
import com.cetc.dto.MenuDTO;
import com.cetc.result.ResponseMsg;
import com.cetc.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import java.util.List; @Configuration
public class CustomHandlerConfiguration { @Autowired
private IUserService userService; /**
* 访问接入点处理
* @return
*/
@Bean
public AuthenticationEntryPoint authenticationEntryPoint() {
AuthenticationEntryPoint entryPoint = (request, response, e) -> {
ResponseMsg<String> responseMsg = new ResponseMsg<>();
responseMsg.setStatus(false);
responseMsg.setBody(e.getMessage());
responseMsg.setErrorCode(SystemErrorCode.NO_LOGIN);
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
response.getWriter().write(JSONObject.toJSONString(responseMsg));
};
return entryPoint;
} /**
* 接入过后问题处理
* @return
*/
@Bean
public AccessDeniedHandler accessDeniedHandler() {
AccessDeniedHandler accessDeniedHandler = (request, response, e) -> {
ResponseMsg<String> responseMsg = new ResponseMsg<>();
responseMsg.setStatus(false);
responseMsg.setBody(e.getMessage());
responseMsg.setErrorCode(SystemErrorCode.NO_PERMISSION);
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
response.getWriter().write(JSONObject.toJSONString(responseMsg));
};
return accessDeniedHandler;
} /**
* 登录成功后的处理
* @return
*/
@Bean
public AuthenticationSuccessHandler authenticationSuccessHandler() {
AuthenticationSuccessHandler authenticationSuccessHandler = (request, response, authentication) -> {
//返回数据
ResponseMsg<List<MenuDTO>> responseMsg = new ResponseMsg<>();
responseMsg.setBody(userService.getMenus());
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
response.getWriter().write(JSONObject.toJSONString(responseMsg));
};
return authenticationSuccessHandler;
} /**
* 登录失败后的处理
* @return
*/
@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
AuthenticationFailureHandler authenticationFailureHandler = (request, response, e) -> {
ResponseMsg<String> responseMsg = new ResponseMsg<>();
responseMsg.setStatus(false);
responseMsg.setBody(e.getMessage());
responseMsg.setErrorCode(SystemErrorCode.ACCOUNT_ERROR);
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
response.getWriter().write(JSONObject.toJSONString(responseMsg));
};
return authenticationFailureHandler;
} /**
* 登出成功后的处理
* @return
*/
@Bean
public LogoutSuccessHandler logoutSuccessHandler() {
LogoutSuccessHandler logoutSuccessHandler = (request, response, authentication) -> {
ResponseMsg<String> responseMsg = new ResponseMsg<>();
responseMsg.setStatus(true);
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
response.getWriter().write(JSONObject.toJSONString(responseMsg));
};
return logoutSuccessHandler;
}
}
其他的就不详细介绍了,基本上都是怎么样去处理,在具体的接入点出现的问题。
7、登录、登出
登录默认的参数为username、password 采用表单方式提交。如果需要修改参数名称可以在loginPage后面加入
.usernameParameter("name")
.passwordParameter("pwd")
说明:默认登录、登出配置的接口不需要实现,默认也是放开的。
8、无需验证访问
在自己开发接口的时候肯定不需要进行权限的访问,这个时候就可以通过配置方式放开具体的请求在.authorizeRequests()配置
.antMatchers("/api/user/register").permitAll()
9、默认会话超时30分钟,可以通过配置修改会话保存时间
server:
servlet:
session:
timeout: 1800s
springboot对security的后端配置的更多相关文章
- SpringBoot + Spring Security 学习笔记(一)自定义基本使用及个性化登录配置
官方文档参考,5.1.2 中文参考文档,4.1 中文参考文档,4.1 官方文档中文翻译与源码解读 SpringSecurity 核心功能: 认证(你是谁) 授权(你能干什么) 攻击防护(防止伪造身份) ...
- spring boot + spring security +前后端分离【跨域】配置 + ajax的json传输数据
1.前言 网上各个社区的博客参差不齐 ,给初学者很大的困扰 , 我琢磨了一天一夜,到各个社区找资料,然后不断测试,遇到各种坑,一言难尽啊,要么源码只有一部分,要么直接报错... 最后实在不行,直接去看 ...
- AgileBoot - 基于SpringBoot + Vue3的前后端快速开发脚手架
AgileBoot 仓库 后端地址:https://github.com/valarchie/AgileBoot-Back-End 技术栈:Springboot / Spring Security / ...
- SpringBoot + Spring Security 学习笔记(五)实现短信验证码+登录功能
在 Spring Security 中基于表单的认证模式,默认就是密码帐号登录认证,那么对于短信验证码+登录的方式,Spring Security 没有现成的接口可以使用,所以需要自己的封装一个类似的 ...
- SpringBoot + Spring Security 学习笔记(三)实现图片验证码认证
整体实现逻辑 前端在登录页面时,自动从后台获取最新的验证码图片 服务器接收获取生成验证码请求,生成验证码和对应的图片,图片响应回前端,验证码保存一份到服务器的 session 中 前端用户登录时携带当 ...
- 基于Springboot集成security、oauth2实现认证鉴权、资源管理
1.Oauth2简介 OAuth(开放授权)是一个开放标准,允许用户授权第三方移动应用访问他们存储在另外的服务提供者上的信息,而不需要将用户名和密码提供给第三方移动应用或分享他们数据的所有内容,OAu ...
- springboot+spring security +oauth2.0 demo搭建(password模式)(认证授权端与资源服务端分离的形式)
项目security_simple(认证授权项目) 1.新建springboot项目 这儿选择springboot版本我选择的是2.0.6 点击finish后完成项目的创建 2.引入maven依赖 ...
- SpringBoot中使用UEditor基本配置(图文详解)
SpringBoot中使用UEditor基本配置(图文详解) 2018年03月12日 10:52:32 BigPotR 阅读数:4497 最近因工作需要,在自己研究百度的富文本编辑器UEditor ...
- SpringBoot:配置文件及自动配置原理
西部开源-秦疆老师:基于SpringBoot 2.1.6 的博客教程 秦老师交流Q群号: 664386224 未授权禁止转载!编辑不易 , 转发请注明出处!防君子不防小人,共勉! SpringBoot ...
随机推荐
- caanimationgroup与CATransaction的区别
动画的组合: caanimationgroup:同一个layer: CATransaction:不同layer: In Core Animation, transactions are a way t ...
- Kali-linux攻击路由器
前面介绍的各种工具,都是通过直接破解密码,来连接到无线网络.由于在一个无线网络环境的所有设备中,路由器是最重要的设备之一.通常用户为了保护路由器的安全,通常会设置一个比较复杂的密码.甚至一些用户可能会 ...
- [Python 网络编程] TCP编程/群聊服务端 (二)
群聊服务端 需求分析: 1. 群聊服务端需支持启动和停止(清理资源); 2. 可以接收客户端的连接; 接收客户端发来的数据 3. 可以将每条信息分发到所有客户端 1) 先搭架子: #TCP Serve ...
- 使用Azcopy在Azure上进行HBase的冷热备份还原
场景 HBase表TaskLog中有20.55G数据(20553078551Byte),目前存放在热存储中,现在要移至冷热储,并进行还原. HBase目录:hbase/data/default 冷目录 ...
- 使用XWAF框架(3)——下载文件
XWAF提供了HttpFileDownloader类用于简化用户下载文件的编码.该类提供了重载方法“downloadFile(String filePath, String fName)”实现下载.程 ...
- Android签名生成和互转
原文链接:http://blog.votzone.com/2018/05/05/android_signature.html Android 的签名有两种方式,一种使用jdk 提供的jarsign ...
- 【OC底层】一个OC对象占用多少内存?
查看一个NSObject对象占用多少内存 1.引入头文件: #import <objc/runtime.h> #import <malloc/malloc.h> 2.代码如下: ...
- Django学习笔记6(iframe、外键插入)
1.{%include 'index.html'%i} 平时很好用的iframe在django里面的不是很好用 django里面提供了{%include 'index.html'%i}的方式来取代了i ...
- MongoDB基础教程
MongoDB 一.下载MongoDB数据库 1.进入MongoDB官网进行下载,网址:https://www.mongodb.com/. 2.下载完成后可进行安装,安装后,并有了MongoDB服务. ...
- 利用wireshark抓取TCP的整个过程分析。
原文地址:https://www.cnblogs.com/NickQ/p/9226579.html 最近,已经很久都没有更新博客了.看看时间,想想自己做了哪些事情,突然发现自己真的是太贪心,到头来却一 ...