栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

(B站云e办)SpringBoot开发项目实战记录(一)(项目搭建配置、逆向工程代码生成、JWT、Security实现登录)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

(B站云e办)SpringBoot开发项目实战记录(一)(项目搭建配置、逆向工程代码生成、JWT、Security实现登录)

SpringBoot开发项目实战记录
  • 一、项目构建
    • 1.1 构建父项目 pom
    • 1.2 构建server项目结构
      • 1. 创建配置文件 application.yml
      • 2. 启动类 YebApplication
      • 3. 常用jar配置
    • 1.3 逆向工程——代码生成器(AutoGenerator)
      • 1. 添加pom依赖
      • 2. 构建代码生成器类
  • 二、JWT 工具类的编写
    • 2.1 配置pom与配置文件
      • 1. pom准备
      • 2. application.yml配置
    • 2.2 工具类的编写
      • 1. JWT工具类编写(JwtTokenUtil)
      • 2. 公共返回对象的封装
  • 三、正式开发
    • 3.1 登录开发(通过security实现安全框架)
      • 1. 创建登录实体类 AdminLoginParam
      • 2. 登录的Controller层
      • 3. 登录的业务层Service
    • 3.2获取用户的信息开发
      • 1.获取用户信息的Controller层(和登录在同一个Controller)
      • 2. 获取用户信息的Service
    • 3.3 Security的配置类
      • 1. SecurityConfig配置
      • 2. Jwt登录授权过滤器实现
      • 3. 未授权结果返回
      • 4. 未登录或登录失效返回
  • 四、Swagger2配置
    • 4.1 pom
    • 4.2 swagger配置类

一、项目构建 1.1 构建父项目 pom


    4.0.0
    
        yeb_server
        yeb_generator
    
    
        org.springframework.boot
        spring-boot-starter-parent
        2.6.2
         
    
    com.jzq
    yeb
    0.0.1-SNAPSHOT
    yeb
    Demo project for Spring Boot
    
        11
    
    pom



1.2 构建server项目结构 1. 创建配置文件 application.yml
server:
  # 端口
  port: 7777

spring:
  # 数据源配置
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/yeb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
    username: root
    password: Seven597
    hikari:
      # 连接池名
      pool-name: DateHikariCP
      # 最小空闲连接数
      minimum-idle: 5
      # 空闲连接存活最大时间,默认600000(10分钟)
      idle-timeout: 180000
      # 最大连接数 (10)
      maximum-pool-size: 10
      # 从连接池返回的连接自动提交
      auto-commit: true
      # 连接最大存活时间,0表示永久,默认为1800000(30分钟)
      max-lifetime: 1800000
      # 连接超时时间, 默认30000 (30秒)
      connection-timeout: 30000
      # 测试连接是否可用的查询语句
      connection-test-query: 1

# Mybatis-plus配置
mybatis-plus:
  # 配置Mapper映射文件
  mapper-locations: classpath*:/mapper

@SpringBootApplication
@MapperScan("com.jzq.server.mapper")
public class YebApplication {
    public static void main(String[] args) {
        SpringApplication.run(YebApplication.class, args);
    }
}

3. 常用jar配置



    4.0.0

    
        yeb
        com.jzq
        0.0.1-SNAPSHOT
    

    yeb_server

    yeb_server
    
    http://www.example.com

    
        UTF-8
        1.8
        1.8
    

    
        
            junit
            junit
            4.11
            test
        

        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.projectlombok
            lombok
            true
        

        
        
            mysql
            mysql-connector-java
            runtime
        

        
        
            com.baomidou
            mybatis-plus-boot-starter
            3.3.1.tmp
        

        
        
            io.springfox
            springfox-swagger2
            2.7.0
        
        
        
            com.github.xiaoymin
            swagger-bootstrap-ui
            1.9.6
        

    

    
        
            
                
                
                    maven-clean-plugin
                    3.1.0
                
                
                
                    maven-resources-plugin
                    3.0.2
                
                
                    maven-compiler-plugin
                    3.8.0
                
                
                    maven-surefire-plugin
                    2.22.1
                
                
                    maven-jar-plugin
                    3.0.2
                
                
                    maven-install-plugin
                    2.5.2
                
                
                    maven-deploy-plugin
                    2.8.2
                
                
                
                    maven-site-plugin
                    3.7.1
                
                
                    maven-project-info-reports-plugin
                    3.0.0
                
            
        
    


1.3 逆向工程——代码生成器(AutoGenerator)

Mybatis-plus地址

1. 添加pom依赖

org.springframework.boot
spring-boot-starter-web



com.baomidou
mybatis-plus-boot-starter
3.3.1.tmp



com.baomidou
mybatis-plus-generator
3.3.1.tmp



org.freemarker
freemarker



mysql
mysql-connector-java
runtime

2. 构建代码生成器类
package com.jzq.generator;

import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.FileOutConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.TemplateConfig;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class CodeGenerator {
    
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + ":");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotEmpty(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + "!");
    }
    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();
        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/yeb-generator/src/main/java");
        //作者
        gc.setAuthor("seven");
        //打开输出目录
        gc.setOpen(false);
        //xml开启 baseResultMap
        gc.setbaseResultMap(true);
        //xml 开启baseColumnList
        gc.setbaseColumnList(true);
        // 实体属性 Swagger2 注解
        gc.setSwagger2(true);
        mpg.setGlobalConfig(gc);
        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://localhost:3306/yeb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia" +
                "/Shanghai");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("root");
        dsc.setPassword("Seven597");
        mpg.setDataSource(dsc);
        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setParent("com.jzq.server")
                .setEntity("pojo")
                .setMapper("mapper")
                .setService("service")
                .setServiceImpl("service.impl")
                .setController("controller");
        mpg.setPackageInfo(pc);
        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
        // to do nothing
            }
        };
        // 如果模板引擎是 freemarker
        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板引擎是 velocity
        // String templatePath = "/templates/mapper.xml.vm";
        // 自定义输出配置
        List focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
                return projectPath + "/yeb-generator/src/main/resources/mapper/"
                        + tableInfo.getEntityName() + "Mapper"
                        + StringPool.DOT_XML;
            }
        });
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);
        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();
        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);
        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        //数据库表映射到实体的命名策略
        strategy.setNaming(NamingStrategy.underline_to_camel);
        //数据库表字段映射到实体的命名策略
        strategy.setColumnNaming(NamingStrategy.no_change);
        //lombok模型
        strategy.setEntityLombokModel(true);
        //生成 @RestController 控制器
        strategy.setRestControllerStyle(true);
        strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
        strategy.setControllerMappingHyphenStyle(true);
        //表前缀
        strategy.setTablePrefix("t_");
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }
}


二、JWT 工具类的编写 2.1 配置pom与配置文件 1. pom准备
        
        
            org.springframework.boot
            spring-boot-starter-security
            2.5.5
        

        
        
        
            io.jsonwebtoken
            jjwt
            0.9.1
        

2. application.yml配置
# JWT
jwt:
  # JWT存储的请求头
  tokenHeader: Authorization
  # JWT 解密加密使用的密钥
  secret: yeb-secret
  # JWT的超期限时间(30*60*24)
  expiration: 604800
  # JWT 负载中拿到开头
  tokenHead: Bearer
2.2 工具类的编写 1. JWT工具类编写(JwtTokenUtil)
package com.jzq.server.config.security;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;


@Component
public class JwtTokenUtil {
    private static final String CLAIM_KEY_USERNAME = "sub";
    private static final String CLAIM_KEY_CREATED = "created";

    @Value("${jwt.secret}")
    private String secret;
    @Value("${jwt.expiration}")
    private Long expiration;


    
    public String generateToken(UserDetails userDetails) {
        Map claims = new HashMap<>();
        claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername());
        claims.put(CLAIM_KEY_CREATED, new Date());

        return generateToken(claims);
    }

    
    public String generateToken(Map claims) {
        System.out.println("secret:"+secret);
        return Jwts.builder()
                .setClaims(claims)                           // 设置载荷
                .setExpiration(generateExpirationDate())     // 设置失效时间
                .signWith(SignatureAlgorithm.HS512, secret)  // 设置签名
                .compact();
    }

    
    public Date generateExpirationDate() {
        // 失效时间是就当前系统时间加 有效时间
        return new Date(System.currentTimeMillis() + expiration*1000);
    }

    
    public String getUserNameFromToken(String token) {
        String username;
        try {
            Claims claims = getUserClaimFromToken(token);
            username = claims.getSubject();
        }catch (Exception e) {
            e.printStackTrace();
            username = null;
        }

        return username;
    }

    
    public Claims getUserClaimFromToken(String token) {
        Claims claims = null;
        try {
            claims = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return claims;
    }


    
    public Boolean validateToken(String token, UserDetails userDetails) {
        String username = getUserNameFromToken(token);   // 终归是来源于token的

        // 然后在token有效的前提下对比用户名是否一致
        return username.equals(userDetails.getUsername()) && !isTokenExpired(token);
    }


    
    public boolean isTokenExpired(String token) {
        Date expireDate = getExpiredDateFromToken(token);   // 拿到载荷里设置的有效时间
        return expireDate.before(new Date());          // 验证载荷里的时间是否以及失效(失效返回true)
    }


    
    public Date getExpiredDateFromToken(String token) {
        Claims claims = getUserClaimFromToken(token);
        return claims.getExpiration();
    }


    
    public boolean canRefresh(String token) {
        return !isTokenExpired(token);
    }


    
    public String refreshToken(String token) {
        Claims claims = getUserClaimFromToken(token);
        claims.put(CLAIM_KEY_CREATED, new Date());

        return generateToken(claims);
    }
}


2. 公共返回对象的封装
package com.jzq.server.config.result;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class RespBean {
    private long code;
    private String message;
    private Object result;

    
    public static RespBean success(String message) {
        return new RespBean(200, message, null);
    }


    
    public static RespBean success(String message, Object result) {
        return new RespBean(200, message, result);
    }


    
    public static RespBean error(String message) {
        return new RespBean(500, message, null);
    }
}

三、正式开发 3.1 登录开发(通过security实现安全框架) 1. 创建登录实体类 AdminLoginParam

swagger文档注解:
@ApiModel : 注释在类上,用于描述
@ApiModelProperty: 注释在属性上, 用于描述和控制权限(是否必填)

package com.jzq.server.pojo;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;



@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value = "AdminLogin对象", description = "")    // swagger文档注解
public class AdminLoginParam {

    @ApiModelProperty(value = "用户名", required = true)
    private String username;
    @ApiModelProperty(value = "密码", required = true)
    private String password;
}
2. 登录的Controller层

swagger:
@Api(tags = “LoginController”) : 标注在类
@ApiOperation(value = “登录后返回token”): 标注在方法

package com.jzq.server.controller;

import com.jzq.server.config.result.RespBean;
import com.jzq.server.pojo.AdminLoginParam;
import com.jzq.server.service.IAdminService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;


@Api(tags = "LoginController")
@RestController
public class LoginController {

    @Autowired
    private IAdminService adminService;

    @ApiOperation(value = "登录后返回token")
    @PostMapping("/login")
    public RespBean login(AdminLoginParam adminLoginParam, HttpServletRequest request) {
        return adminService.login(adminLoginParam.getUsername(), adminLoginParam.getPassword());
    }
}

3. 登录的业务层Service
  1. 接口层
package com.jzq.server.service;

import com.jzq.server.config.result.RespBean;
import com.jzq.server.pojo.Admin;
import com.baomidou.mybatisplus.extension.service.IService;

import javax.servlet.http.HttpServletRequest;


public interface IAdminService extends IService {

    
    RespBean login(String username, String password, HttpServletRequest request);
}

  1. 接口实现层

注意更新security登录用户对象
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());//第二个参数为口令(密码)不用传
通过SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken)设置

package com.jzq.server.service.impl;

import com.jzq.server.config.result.RespBean;
import com.jzq.server.config.security.JwtTokenUtil;
import com.jzq.server.pojo.Admin;
import com.jzq.server.mapper.AdminMapper;
import com.jzq.server.service.IAdminService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;


@Service
public class AdminServiceImpl extends ServiceImpl implements IAdminService {

    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private PasswordEncoder passwordEncoder;   // 判断密码是否一致
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Value("${jwt.tokenHead}")    // 根据value注解拿到yml中设置的token头
    private String tokenHead;

    
    @Override
    public RespBean login(String username, String password, HttpServletRequest request) {
        // 登录
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        if (userDetails==null && !passwordEncoder.matches(password, userDetails.getPassword())) {
            return RespBean.error("用户名或者密码不正确");
        }
        if (!userDetails.isEnabled()) {
            return RespBean.error("账号被禁用,请练习管理员");
        }

        // 更新security登录用户对象
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new
                UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());//第二个参数为口令(密码)不用传
        SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);

        // 生成token
        String token = jwtTokenUtil.generateToken(userDetails);
        Map tokenMap = new HashMap<>();
        tokenMap.put("token", token);
        tokenMap.put("tokenHead", tokenHead);
        return RespBean.success("登录成功", tokenMap);
    }
}

3.2获取用户的信息开发 1.获取用户信息的Controller层(和登录在同一个Controller)

⭐ Principal对象: principal是我们设置到security中存的全局的用户信息

import *;



@Api(tags = "LoginController")
@RestController
public class LoginController {

    @Autowired
    private IAdminService adminService;

    @ApiOperation(value = "获取当前登录用户的信息")
    @GetMapping("/admin/info")
    public Admin getAdminInfo(Principal principal) {
        // principal是我们设置到security中存的全局的用户信息
        if (principal == null) {
            return null;
        }
        String username = principal.getName();
        Admin admin = adminService.getAdminByUserName(username);
        admin.setPassword(null);
        return admin;
    }


    @ApiOperation(value = "用户退出登录")
    @PostMapping("/logout")
    private RespBean logout(){
        return RespBean.success("注销成功!");
    }
}

2. 获取用户信息的Service
  1. 接口层
    RespBean getAdminByUserName(String username);
  1. 实现层

⭐ adminMapper.selectOne(new QueryWrapper().eq(“username”, username).eq(“enable”, true));
这里是Mybatis-Plus中获取Admin实体类对应数据库表的数据,条件可以链式判断eq(), 两个参数前面的是指定列,后面是判断该列的值

@Service
public class AdminServiceImpl extends ServiceImpl implements IAdminService {

    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private PasswordEncoder passwordEncoder;   // 判断密码是否一致
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Value("${jwt.tokenHead}")    // 根据value注解拿到yml中设置的token头
    private String tokenHead;

    @Autowired
    private AdminMapper adminMapper;

     
    @Override
    public Admin getAdminByUserName(String username) {
        return adminMapper.selectOne(new QueryWrapper().eq("username", username).eq("enable", true));
    }
}

3.3 Security的配置类 1. SecurityConfig配置
  1. 我们主要配置了通过jwt我们无序使用csrf, 以及禁用了cache,使用cookie技术存token。(通过重写configure)
  1. 添加jwt登录过滤器以及未授权或未登录返回结果
  1. 配置放行接口

在配置类下方是注入的一些Bean,包括我们自己用到的passwordEncoder、userDetailsService。以及jwt登录过滤与未授权和未登录的结果返回
package com.jzq.server.config.security;


import com.jzq.server.pojo.Admin;
import com.jzq.server.service.IAdminService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.Filter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private IAdminService adminService;


    @Override
    public void configure(WebSecurity web) throws Exception {
        // 设置放行访问
         web.ignoring().antMatchers(
                 "/login",
                 "/logout",
                 "/css
public class JwtAuthencationTokenFilter extends OncePerRequestFilter {

    @Value("${jwt.tokenHeader}")
    private String tokenHeader;
    @Value("${jwt.tokenHead}")
    private String tokenHead;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String authHeader = request.getHeader(tokenHeader);  // 获取token值
        // 存在token  (获取的token不为空,且token前面携带的表示是我们设置的标识)
        if (authHeader!=null && authHeader.startsWith(tokenHead)){
            String authToken = authHeader.substring(tokenHead.length());  // 截取下除了头部标识以后的token
            String username = jwtTokenUtil.getUserNameFromToken(authToken);   // 通过token就可以拿到用户名(解析荷载部分)
            // 看看username存在,但是未登录(就是检测是不是设置在security全局中)
            if (username != null && SecurityContextHolder.getContext().getAuthentication()==null) {
                // 登录
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);

                // 验证token是否有效,重新设置用户对象
                if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                    UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                    authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
                }
            }
        }

        // 最后放行
        filterChain.doFilter(request,response);
    }
}

3. 未授权结果返回
package com.jzq.server.config.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.jzq.server.config.result.RespBean;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;


public class RestfulAccessDeniedHandel implements AccessDeniedHandler {
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        PrintWriter printWriter = response.getWriter();

        RespBean respBean = RespBean.error("权限不足,请联系管理员");
        respBean.setCode(403);
        printWriter.write(new ObjectMapper().writevalueAsString(respBean));
        printWriter.flush();  // 强推到浏览器
        printWriter.close();
    }
}

4. 未登录或登录失效返回
package com.jzq.server.config.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.jzq.server.config.result.RespBean;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Controller;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;



@Controller
public class RestAuthorizationEnrtyPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json");
        PrintWriter printWriter = response.getWriter();

        RespBean respBean = RespBean.error("登录失效,请重新登录");
        respBean.setCode(401);
        printWriter.write(new ObjectMapper().writevalueAsString(respBean));
        printWriter.flush();  // 强推到浏览器
        printWriter.close();

    }
}

四、Swagger2配置 4.1 pom
        
            io.springfox
            springfox-swagger2
            2.7.0
        
        
        
            com.github.xiaoymin
            swagger-bootstrap-ui
            1.9.6
        
4.2 swagger配置类

配置了文档访问地址
以及配置了全局配置Authorization

package com.jzq.server.config.Swagger;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.documentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.List;



@Configuration
@EnableSwagger2
public class Swagger2Config {

    @Bean
    public Docket createRestApi(){
        return new Docket(documentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.jzq.server.controller"))
                .paths(PathSelectors.any())
                .build()
                .securityContexts(securityContexts())
                .securitySchemes(securitySchemes());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("云e办接口文档")
                .description("描述")
                .contact(new Contact("jzq", "http:localhost:7777/doc.html", "xxx@xxx.com"))
                .build();
    }

    private List securitySchemes() {
        // 设置请求头
        List result = new ArrayList<>();
        ApiKey apiKey = new ApiKey("Authorization", "Authorization", "Header");
        result.add(apiKey);
        return result;
    }

    private List securityContexts() {
        // 设置需要登录认证的路径
        List result = new ArrayList<>();
        result.add(getContextByPath("/test/.*"));
        return result;
    }

    private SecurityContext getContextByPath(String pathRegex) {
        return SecurityContext.builder()
                .securityReferences(defaultAuth())
                .forPaths(PathSelectors.regex(pathRegex))
                .build();
    }

    private List defaultAuth() {
        List result = new ArrayList<>();
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        result.add(new SecurityReference("Authorization", authorizationScopes));
        return result;
    }
}

例如:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/697464.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号