SecurityConfig配置


一、SecurityConfig

import com.example.anyimenchuang.common.handler.AccessDeniedHandlerImpl;
import com.example.anyimenchuang.common.handler.AuthenticationEntryPointImpl;
import com.example.anyimenchuang.handler.SecurityLogoutSuccessHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启权限注解功能
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Resource
    private AccessDeniedHandlerImpl accessDeniedHandler;

    @Resource
    private AuthenticationEntryPointImpl authenticationEntryPoint;
    @Resource
    private SecurityLogoutSuccessHandler securityLogoutSuccessHandler;

    //创建BCryptPasswordEncoder 注入容器 加密方式
    @Bean
    public PasswordEncoder passwordEncoder() {
        //当你将此对象注入容器时,就会自动将密码进行bc的比对校验。
        //如果输入的明文密码与数据库中的加密密码不匹配则报错。
        //切数据库中必须存储为bc加密的密码
        return new BCryptPasswordEncoder();
    }


    @Override   //配置登录的路径 及需要认证的路径
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()//关闭csrf
                //不通过Session获取SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                // 允许匿名访问
                .antMatchers("/user/add", "/user/login").anonymous()
                //放行swagger
                .antMatchers(
                        "/swagger-ui.html",
                        "/swagger-ui/index.html",
                        "/swagger-resources/**",
                        "/webjars/**",
                        "/swagger-ui/**",
                        "/v3/**",
                        "/api/**",
                        "/swagger-ui.html/**"
                ).permitAll()
//                .antMatchers("/hello").permitAll() //允许登录或者未登录都可访问
//                .antMatchers("/testCors").hasAuthority("system:dept:list222")
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated();

        http.logout()
                .logoutUrl("/user/logout")
                .logoutSuccessHandler(securityLogoutSuccessHandler)
                .deleteCookies("JSESSIONID");
        //添加过滤器
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        //配置异常处理器
        http.exceptionHandling()
                //配置认证失败及授权失败处理器
                .authenticationEntryPoint(authenticationEntryPoint)
                .accessDeniedHandler(accessDeniedHandler);
        //设置跨越
        http.cors();

    }


    @Bean
    @Override  //需要通过AuthenticationManager的authenticate方法进行用户认证,所有需要在此将其注入容器
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

}


二、其他配置

1.JwtAuthenticationTokenFilter

代码如下(示例):

import com.alibaba.fastjson2.JSON;
import com.example.anyimenchuang.common.LoginUser;
import com.example.anyimenchuang.common.utils.sys.JwtUtils;
import io.jsonwebtoken.Claims;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;


/**
 * @Description : jwt认证过滤器  定义好后需要进行配置指定的位置 在SecurityConfig中进行配置
 * 当调用其他接口时需要携带token,此处进行token验证,验证通过则放行
 */
@Component //token校验过滤器
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        // 获取token
        String token = request.getHeader("token");
        if (StringUtils.isBlank(token)) {//如果为空
            //放行  因为后面还有其他的过滤器会进行判断并提示
            filterChain.doFilter(request, response);
            return;
        }
        // 解析token
        String userId;
        try {
            Claims claims = JwtUtils.parseJWT(token);
            userId = claims.getSubject();

        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("token非法");
        }

        // 从redis中获取用户信息
        String redisKey = "user:" + userId;

        String value = redisTemplate.opsForValue().get(redisKey);
        LoginUser loginUser = JSON.parseObject(value, LoginUser.class);//会根据类型自动转换
        if (Objects.isNull(loginUser)) {
            throw new RuntimeException("用户未登录");
        }
        // 存入SecurityContextHolder
        // 获取权限信息封装到Authentication中  第三个为获取权限loginUser.getAuthorities()
        UsernamePasswordAuthenticationToken userToken =
                new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(userToken);
        // 放行
        filterChain.doFilter(request, response);
    }
}

2.AccessDeniedHandlerImpl

代码如下(示例):

import com.alibaba.fastjson2.JSON;
import com.example.anyimenchuang.common.SysResult;
import com.example.anyimenchuang.common.utils.sys.WebUtils;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Description : 授权失败处理器
 */
@Component
public class AccessDeniedHandlerImpl implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) {

        SysResult result = new SysResult().setCode(403).setMsg("您的权限不足");

        String json = JSON.toJSONString(result);
        //处理异常
        WebUtils.renderString(response, json);
    }
}


3.AccessDeniedHandlerImpl

代码如下(示例):

import com.alibaba.fastjson2.JSON;
import com.example.anyimenchuang.common.SysResult;
import com.example.anyimenchuang.common.utils.sys.WebUtils;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Description : 自定义认证失败异常处理器
 */
@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) {
        SysResult result = new SysResult().setCode(401).setMsg("用户认证失败请查询登录");
        String json = JSON.toJSONString(result);
        //处理异常
        WebUtils.renderString(response, json);
    }
}



4.AccessDeniedHandlerImpl

代码如下(示例):

import com.alibaba.fastjson2.JSON;
import com.example.anyimenchuang.common.JSONResult;
import com.example.anyimenchuang.common.utils.sys.JwtUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


@Component
public class SecurityLogoutSuccessHandler implements LogoutSuccessHandler {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    @Resource
    private RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();

    public SecurityLogoutSuccessHandler() {
    }

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
            throws IOException {

        String token = request.getHeader("token");
        int userId = Integer.parseInt(JwtUtils.parseJWT(token).getSubject());
        redisTemplate.delete("user:" + userId);

        logger.info("退出成功");

        response.setContentType("application/json;charset=utf-8");
        response.getWriter().write(JSON.toJSONString(new JSONResult<>(200, "success")));
    }
}



  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值