引入依赖
org.springframework.boot
spring-boot-starter-security
编写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 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的提交
//发送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)
})
添加成功
引入依赖
org.thymeleaf.extras
thymeleaf-extras-springsecurity5
前端引入
模块设置
满足moderator权限时才显示
先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦