SpringBoot+SpringSecurity+Jwt+Mybatis-Plus+Swwager

因公司业务为PC端后台管理居多,session有这得天独厚优势。

本月有个项目,有一端是小程序。天然不支持Cookie。因此打算用Jwt token方式

博客简单讲解一下与Springboot+SpringSecurity+SpringSession+Redis+Mybatis-Plus+Swwager搭建的区别

 

pom

去掉 SpringSession Redis依赖

        <!-- jwt -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

 

Swagger配置

@Configuration
@EnableSwagger2
public class SwaggerConfig {
    @Bean
    public Docket createRestApi(){
        // 添加请求参数,我们这里把token作为请求头部参数传入后端
        ParameterBuilder parameterBuilder = new ParameterBuilder();
        List<Parameter> parameters = new ArrayList<Parameter>();
        parameterBuilder.name("Authorization").description("令牌").modelRef(new ModelRef("string")).parameterType("header")
                .required(false).build();
        parameters.add(parameterBuilder.build());
        return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any()).build().globalOperationParameters(parameters);
    }

    private ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                .title("SpringBoot API Doc")
                .description("This is a restful api document of Spring Boot.")
                .version("1.0")
                .build();
    }
}

 

SpringSecurity配置

重要最后2行代码

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
                    @Override
                    public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                        object.setAccessDecisionManager(customUrlDecisionManager);
                        object.setSecurityMetadataSource(customFilterInvocationSecurityMetadataSource);
                        return object;
                    }
                })
                .and()
                .formLogin()
                .successHandler((req,resp,authentication) -> {
                    SysUser user = (SysUser) authentication.getPrincipal();
                    user.setPassword(null);
                    Map<String,Object> map = new HashMap<>(2);
                    map.put("user",user);
                    String token = JwtTokenUtils.generateToken(authentication);
                    map.put("token",token);


                    RespResult.success(resp,"登录成功",map);
                })
                .failureHandler((req,resp,failed) -> {
                    String msg;
                    if(failed instanceof LockedException){
                        msg = "账户被锁定,请联系管理员!";
                    }else if (failed instanceof BadCredentialsException){
                        msg = "用户名或者密码输入错误,请重新输入!";
                    }else if(failed instanceof DisabledException){
                        msg = "账户被禁用,请联系管理员!";
                    }else if (failed instanceof AccountExpiredException){
                        msg = "账户过期,请联系管理员!";
                    }else if (failed instanceof CredentialsExpiredException){
                        msg = "密码过期,请联系管理员!";
                    }else{
                        msg = "other";
                    }

                    RespResult.failure(resp,msg);
                })
                .permitAll()
                .and()
                .logout()
                .logoutSuccessHandler((req,resp,authentication) -> {
                    RespResult.success(resp,"注销登录成功");
                })
                .permitAll()
                .and().csrf().disable()
                .exceptionHandling().authenticationEntryPoint((req,resp,exception) -> {
                    if (exception instanceof InsufficientAuthenticationException) {
                        RespResult.accessDenied(resp,"尚未登录,请登录");
                    }else{
                        RespResult.accessDenied(resp,"请求失败,请联系管理员!");
                    }
                })
                .accessDeniedHandler((req,resp,exception) -> {
                    RespResult.accessDenied(resp,exception.getMessage());
                });
        //Session的创建状态永远不会创建HttpSession
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        //新增过滤器
        http.addFilterBefore(new JwtAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);
    }

Jwt拦截器

作用:当有携带token,验证token并解析放入ContextHolder,给Security用


/**
 * @author cmy
 * @date 2020/10/16 15:54
 */
public class JwtAuthenticationFilter extends BasicAuthenticationFilter {
    @Autowired
    public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

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


        Authentication authentication = null;
        String token = JwtTokenUtils.getToken(request);
        if(token != null) {
            if(SecurityUtils.getAuthentication() == null) {
                Claims claims = JwtTokenUtils.getClaimsFromToken(token);
                if(claims == null) {
                    RespResult.failure(response,"无效的token,或token已过期");
                    return;
                }
                String userName = claims.getSubject();
                String userId = claims.getId();
                if(userName == null || userId == null) {
                    RespResult.failure(response,"无效的token");
                    return;
                }
                if(JwtTokenUtils.isTokenExpired(token)) {
                    RespResult.failure(response,"token已过期");
                    return;
                }
                Object authors = claims.get(JwtTokenUtils.AUTHORITIES);
                List<GrantedAuthority> authorities = new ArrayList<>();
                if (authors != null && authors instanceof List) {
                    for (Object object : (List) authors) {
                        authorities.add(new SimpleGrantedAuthority((String) ((Map) object).get("authority")));
                    }
                }
                SysUser user = new SysUser();
                user.setId(Integer.parseInt(userId));
                user.setUsername(userName);
                authentication = new UsernamePasswordAuthenticationToken(user, null, authorities);
            }else{
                if(JwtTokenUtils.validateToken(token, SecurityUtils.getUsername(SecurityUtils.getAuthentication()))) {
                    authentication = SecurityUtils.getAuthentication();
                }else{
                    RespResult.failure(response,"无效的token,或token已过期");
                    return;
                }
            }

            SecurityContextHolder.getContext().setAuthentication(authentication);
            chain.doFilter(request, response);
        }else{
            chain.doFilter(request, response);
        }

    }
}

 

下载Demo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值