一、SpringSecurity介绍
- 简介
SpringSecurity是一个专注于java应用程序提供身份认证和授权的框架,它的强大之处在于它可以轻松扩展以满足自定义的需求 - 特征
– 对身份的认证和授权提供全面的、可扩展的支持。
– 防止各种攻击,如会话固定攻击、点击劫持、csrf攻击等。
– 支持与Servlet API,Spring MVC等web技术支持 - SpringSecurity底层是通过11钟过滤器进行实现,属于JavaEE层面
SpringSecurity底层详解网站推荐:http://www.spring4all.com/article/428
二、利用SpringSecurity进行权限控制
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
编写config类
对未登录,权限不足以及退出时进行过滤
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter implements CommunityConstant {
//忽略对静态资源的拦截
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//授权
http.authorizeRequests()
//需要授权的请求
.antMatchers(
"/user/setting",
"/user/upload",
"/discuss/add",
"/comment/add/**",
"/letter/**",
"/notice/**",
"/like",
"/follow",
"/followee/**",
"/follower/**"
)
//上述请求需要的身份
.hasAnyAuthority(
AUTHORITY_USER,
AUTHORITY_ADMIN,
AUTHORITY_MODERATOR
)
//拥有身份时允许的行为
.anyRequest().permitAll();
//权限不够时的操作
http.exceptionHandling()
//没有登陆
.authenticationEntryPoint(new AuthenticationEntryPoint() {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
//当请求头是x-requested-with=XMLHttpRequest时说明是异步请求,返回JSON字符串
String xRequestedWith = request.getHeader("x-requested-with");
//if (xRequestedWith.equals("XMLHttpRequest")) {会报空指针异常
if ("XMLHttpRequest".equals(xRequestedWith)) {
response.setContentType("application/plain;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write(CommunityUtil.getJSONString(403, "您还没有登录!"));
} else {
response.sendRedirect(request.getContextPath() + "/login");
}
}
})
//权限不足
.accessDeniedHandler(new AccessDeniedHandler() {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
//当请求头是x-requested-with=XMLHttpRequest时说明是异步请求,返回JSON字符串
String xRequestedWith = request.getHeader("x-requested-with");
//if (xRequestedWith.equals("XMLHttpRequest")) {会报空指针异常
if ("XMLHttpRequest".equals(xRequestedWith)) {
response.setContentType("application/plain;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.write(CommunityUtil.getJSONString(403, "您没有访问的权限!"));
} else {
response.sendRedirect(request.getContextPath() + "/denied");
}
}
});
//security底层默认会拦截/logout请求,进行退出处理,覆盖他的逻辑,才能执行我们自己的推出代码
http.logout().logoutUrl("/securitylogout");//写一个没有的请求欺骗springSecurity
}
}
if (xRequestedWith.equals(“XMLHttpRequest”)) 会报空指针异常,因为xRequestedWith可能为null
改为if (“XMLHttpRequest”.equals(xRequestedWith)) 防止此错误
编写userService类实现获取用户权限的方法
@Override
public Collection<? extends GrantedAuthority> getAuthorities(int userId) {
//获得当前登录用户
User user = this.findUserById(userId);
//将用户权限装入List
List<GrantedAuthority> list = new ArrayList<>();
list.add(new GrantedAuthority() {
@Override
public String getAuthority() {
switch (user.getType()){
case 1:
return AUTHORITY_ADMIN;
case 2:
return AUTHORITY_MODERATOR;
default:
return AUTHORITY_USER;
}
}
});
return list;
}
将认证信息写入过滤器
写入过滤器的preHandle方法,在每一次请求前都调用
//构建用户认证的结果,并存入SecurityContext,以便于security进行授权
Authentication authentication = new UsernamePasswordAuthenticationToken(user, user.getPassword(), userService.getAuthorities());
SecurityContextHolder.setContext(new SecurityContextImpl(authentication));
并在请求结束时的afterCompletion方法中清楚认证
SecurityContextHolder.clearContext();
防止csrf攻击
- csrf攻击:
在用户提交表单时,不法网站可能窃取用户提交的信息进行提交从而造成安全问题 - 解决办法
springsecurity中在用户同步提交表单时设置了一个隐藏的token,不但会对用户提交的信息进行核实,还会对token进行核实,在异步提交的时候则需要自行在前端加入token提交 - 异步请求时徐手动添加token的提交
<!--生成csrf令牌-->
<meta name="_csrf" th:content="${_csrf.token}">
<meta name="_csrf_header" th:content="${_csrf.headerName}">
//发送ajax请求前,将csrf令牌设置到请求的消息头中
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function (e, xhr, options) {
xhr.setRequestHeader(header, token)
})
添加成功
三、整合前端模板
引入依赖
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
前端引入
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
模块设置
<button type="button" class="btn btn-danger btn-sm " id="topBtn" th:disabled="${post.type==1}" sec:authorize="hasAnyAuthority('moderator')">置顶</button>
满足moderator权限时才显示
相关文章
暂无评论...