如果你没有看第一篇文章,建议你去看一下
文章链接

  • 好好看每一步
  • 你可以知道什么是逆向工程
  • 你可以在这里好好学习一下登录模块
  • 由于本的sql语句放在001云E办项目创建

一、 逆向工程(创建AutoGenerator项目)

  1. AutoGenerator是什么
    AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Pojo、Mapper、
    Mapper XML、Service、Controller 等各个模块的代码。
  2. AutoGenerator能干什么
    对于单表而言,几乎是一个全能的工具,极大的提升了开发效率。更多的关注业务逻辑的实现。
  3. 怎么使用呢?
    创建建AutoGenerator项目:这个项目时从maven里面创建原始类型,勾选那个archer-quickstart
    AutoGenerator本身和我们项目没有关联,所以可以单独新建为一个Project,这边也做成Maven聚
    合项目里的一个子项目
  4. 导入依赖
<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>voa</artifactId><groupId>com.mldn</groupId><version>0.0.1-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>voa-generator</artifactId><name>voa-generator</name><!-- FIXME change it to the project's website --><url>http://www.example.com</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compiler.source>1.7</maven.compiler.source><maven.compiler.target>1.7</maven.compiler.target></properties><dependencies><!--web 依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--mybatis-plus 依赖--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.3.1.tmp</version></dependency><!--mybatis-plus 代码生成器依赖--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.3.1.tmp</version></dependency><!--freemarker 依赖--><dependency><groupId>org.freemarker</groupId><artifactId>freemarker</artifactId></dependency><!--mysql 依赖--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency></dependencies><build><pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --><plugins><!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle --><plugin><artifactId>maven-clean-plugin</artifactId><version>3.1.0</version></plugin><!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging --><plugin><artifactId>maven-resources-plugin</artifactId><version>3.0.2</version></plugin><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.8.0</version></plugin><plugin><artifactId>maven-surefire-plugin</artifactId><version>2.22.1</version></plugin><plugin><artifactId>maven-jar-plugin</artifactId><version>3.0.2</version></plugin><plugin><artifactId>maven-install-plugin</artifactId><version>2.5.2</version></plugin><plugin><artifactId>maven-deploy-plugin</artifactId><version>2.8.2</version></plugin><!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle --><plugin><artifactId>maven-site-plugin</artifactId><version>3.7.1</version></plugin><plugin><artifactId>maven-project-info-reports-plugin</artifactId><version>3.0.0</version></plugin></plugins></pluginManagement></build>
</project>
  1. 编写CodeGenerator工具类来使用
package com.mldn.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;
/*** 执行 main 方法控制台输入模块表名回车自动生成对应项目目录中** @author zhoubin* @since 1.0.0*/
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();final String projectPath = System.getProperty("user.dir");gc.setOutputDir(projectPath + "/yeb-generator/src/main/java");//作者gc.setAuthor("zhoubin");//打开输出目录gc.setOpen(false);//xml开启 BaseResultMapgc.setBaseResultMap(true);//xml 开启BaseColumnListgc.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("111");mpg.setDataSource(dsc);// 包配置PackageConfig pc = new PackageConfig();pc.setParent("com.xxxx").setEntity("pojo").setMapper("mapper").setService("service").setServiceImpl("service.impl").setController("controller");mpg.setPackageInfo(pc);// 自定义配置InjectionConfig cfg = new InjectionConfig() {@Overridepublic void initMap() {// to do nothing}};// 如果模板引擎是 freemarkerString templatePath = "/templates/mapper.xml.ftl";// 如果模板引擎是 velocity// String templatePath = "/templates/mapper.xml.vm";// 自定义输出配置List<FileOutConfig> focList = new ArrayList<>();// 自定义配置会被优先输出focList.add(new FileOutConfig(templatePath) {@Overridepublic String outputFile(TableInfo tableInfo) {// 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!//return projectPath + "/yeb-generator/src/main/resources/mapper/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_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();
//执行 执行main方法,在控制台直接输出表名,多个表名用 , 隔开 结果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();}
}
  1. 测试
    运行我们编写的那个类中的main方法,然后在下面输入我们的表就可以了,下面的表的话(就是数据库里面对应的表)然后会自动生成对应的mapper文件呀

二、登录模块

(一)前提准备

1、首先导入依赖

     <!-- Swagger第三方ui依赖 --><dependency><groupId>com.github.xiaoymin</groupId><artifactId>swagger-bootstrap-ui</artifactId><version>1.9.6</version></dependency><!-- swagger2 依赖 --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.7.0</version></dependency><!--security 依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><!--JWT 依赖--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.0</version></dependency>

2、application.properteis配置

#jwt存储的请求头
jwt.tokenHeader=Authorization
#jwt 加密使用的秘钥
jwt.secret=yeb-secret
#jwt的超限时间
jwt.expiration=604800
#jwt负载中拿到的开头
jwt.tokenHead=Bearer

3、导入一步生成的文件

(二)正式的义务逻辑实现

从接下来开始,我的建议是每一步都自己动手编写一次,不然你会后悔的

1、编写JWT类

package com.xxxx.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;/*** 有生成token,判断token是否失效等方法* 如果你看不懂,建议去看我的jwt整合SpringSecurity文章的前面部分,对JWT有个大致的学习**/
@Component
public class JwtTokenUtil {//用户名的keyprivate static final  String CLAIM_KEY_USERNAME = "sub";//jwt的创建时间private static final  String CLAIM_KEY_CREATED = "created";//jwt秘钥@Value("${jwt.secret}")//去配置文件取得private String secret;//jwt的失效时间@Value("${jwt.expiration}")private Integer expiration;//1根据用户名生成token//2从生成的token里面拿用户名//3判断token是否失效//4判断token是否可以刷新/*** 方法一:根据用户名生成token* 根据用户信息生成对应的token* @param userDetails* @return*/public String generateToken(UserDetails userDetails) {Map<String,Object> claims = new HashMap<>();claims.put(CLAIM_KEY_USERNAME,userDetails.getUsername());//为xxx用户名生成tokenclaims.put(CLAIM_KEY_CREATED,new Date());//设置创建时间return generateToken(claims);}/*** 根据荷载生成JWT Token* @param claims* @return*/private String generateToken(Map<String,Object> claims) {return Jwts.builder().setClaims(claims)//配置的失效时间:当前时间System.currentTimeMillis().setExpiration(new Date(System.currentTimeMillis() + expiration*1000))//配置的是秘钥.signWith(SignatureAlgorithm.ES512,secret).compact();}/*** 方法二* 从token里面获取登录的用户名* @param token* @return*/public String getUserNameFromToken(String token) {String username;try {Claims claims = getClaimsFormToken(token);//调用获取荷载的方法username = claims.getSubject();//从荷载里面获取用户名} catch (Exception e) {//用户名不存在username = null;}return username;}//从token中获取荷载private Claims getClaimsFormToken(String token) {Claims claims = null;try {claims = Jwts.parser().setSigningKey(secret)//指定秘钥.parseClaimsJws(token)//指定token.getBody();} catch (Exception e) {e.printStackTrace();}return claims;}/*** 方法三:判断token是否过期*      1、判断token是否过期*      2、token荷载里面的用户名和UserDetails里面用户名是否一致* @param token* @param userDetails* @return*/public boolean validateToken(String token,UserDetails userDetails) {String username = getUserNameFromToken(token);return username.equals(userDetails.getUsername()) && !isTokenExpired(token) ;}//判断token是否失效private boolean isTokenExpired(String token) {Date expireDate = getExpiredDateFromToken(token);return expireDate.before(new Date());}private Date getExpiredDateFromToken(String token) {Claims claims = getClaimsFormToken(token);return claims.getExpiration();}/*** 方法四* 判断是否可以被刷新* @param token* @return*/public boolean canRefresh(String token) {return !isTokenExpired(token);}/*** 方法五:刷新token* @param token* @return*/public String refreshToken(String token) {Claims claims = getClaimsFormToken(token);claims.put(CLAIM_KEY_CREATED,new Date());return generateToken(claims);}}

2、返回类信息类

package com.xxxx.server.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;/*** 公共返回对象** @author zhoubin* @since 1.0.0*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class RespBean {//状态码private long code;//提示信息private String message;//返回对象private Object obj;/*** 成功返回结果* @param message* @return*/public static RespBean success(String message){return new RespBean(200,message,null);}/*** 成功返回结果* @param message* @param obj* @return*/public static RespBean success(String message,Object obj){return new RespBean(200,message,obj);}/*** 失败返回结果* @param message* @return*/public static RespBean error(String message){return new RespBean(500,message,null);}/*** 失败返回结果* @param message* @param obj* @return*/public static RespBean error(String message,Object obj){return new RespBean(500,message,obj);}
}

3、编写我们的登录专用类

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value = "AdminLogin对象",description = "")
public class AdminLoginParam {@ApiModelProperty(value = "用户名",required = true)private String username;@ApiModelProperty(value = "密码",required = true)private String password;/*@ApiModelProperty(value = "验证码",required = true)private String code;*/
}

4、开始我们的登录逻辑了

(1)思路

肯定用户登录发起请求的一个任务,然后输入用户名和密码验证码和后端的进行交互,后端的处理如下:

  • 编写请求的Controller,有一个登录的方法,进行请求拦截
  • 编写对应的Service层,去调用我们的Mapper层,查询数据库
  • 编写对应的Mapper层,去处理我们的SQL语句
  • 编写对应的xml文件,查询

(2)我们的主类Admin

  • 首先它的属性和我们的数据一定要匹配
  • 然后要实现我们的UserDetails 接口,然后对方法进行处理
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_admin")
@ApiModel(value="Admin对象", description="")
public class Admin implements Serializable, UserDetails {private static final long serialVersionUID = 1L;@ApiModelProperty(value = "id")@TableId(value = "id", type = IdType.AUTO)private Integer id;@ApiModelProperty(value = "姓名")private String name;@ApiModelProperty(value = "手机号码")private String phone;@ApiModelProperty(value = "住宅电话")private String telephone;@ApiModelProperty(value = "联系地址")private String address;@ApiModelProperty(value = "是否启用")@Getter(AccessLevel.NONE)private Boolean enabled;@ApiModelProperty(value = "用户名")private String username;@ApiModelProperty(value = "密码")private String password;@ApiModelProperty(value = "用户头像")private String userFace;@ApiModelProperty(value = "备注")private String remark;@ApiModelProperty(value = "角色")@TableField(exist = false)private List<Role> roles;@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {//权限先空着,后面再来编写return null;}@Overridepublic boolean isAccountNonExpired() {return true;}@Overridepublic boolean isAccountNonLocked() {return true;}@Overridepublic boolean isCredentialsNonExpired() {return true;}@Overridepublic boolean isEnabled() {return enabled;}
}

(3)登录的Controller层

import com.xxxx.server.pojo.AdminLoginParam;
import com.xxxx.server.pojo.RespBean;
import com.xxxx.server.sevice.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;@RestController
@Api(tags = "LoginController")
public class LoginController {@Autowiredprivate IAdminService adminService;@ApiOperation(value = "登录之后返回token")@PostMapping("/login")public RespBean login(AdminLoginParam adminLoginParam, HttpServletRequest request) {return adminService.login(adminLoginParam.getUsername(),adminLoginParam.getPassword(),request);}
}

(4)Service层

每一句话都弄清楚,不懂的给我私信,我基本每天都看csdn的

/*** 登录的服务类*/
public interface IAdminService extends IService<Admin> {/*** 登录之后返回token* @param username* @param password* @param request* @return* */RespBean login(String username, String password, HttpServletRequest request);}
@Service
public class IAdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements IAdminService {@Autowiredprivate UserDetailsService userDetailsService;@AutowiredPasswordEncoder passwordEncoder;@AutowiredJwtTokenUtil jwtTokenUtil;@Value("${jwt.tokenHead")private String tokenHead;//头部信息/*** 登录之后返回token* @param username* @param password* @param request* @return*/@Overridepublic RespBean login(String username, String password, HttpServletRequest request) {//这里做一点说明,可能第一次做项目的人不是很理解,为什么这样搞//这里其实就是SpringSecurity给我提供的,如果不懂说明你SpringSecurity不行,可以去复习一下//其实就是我们编写的主类Admin实现了UserDetails和这个呼应起来,实现认证的流程UserDetails userDetails = userDetailsService.loadUserByUsername(username);if (null == userDetails || !passwordEncoder.matches(password,userDetails.getUsername())) {return RespBean.error("用户名或者密码不正确");}if (!userDetails.isEnabled()) {return RespBean.error("账号被禁用,请联系管理员");//其实这里有很多处理的,暂时这样了解}//如果上面的都通过了,说明没问题了,可以发放token令牌了String token = jwtTokenUtil.generateToken(userDetails);Map<String,String> tokenMap = new HashMap<>();tokenMap.put("token",token);//发放的tokentokenMap.put("tokenHead",tokenHead);//给前端的请求头,下次会带上//上面两步都完成了,我们编写token的时候,说了是要有时候有更新token的,我们用户也是会更新的//我们这里的更新可以用SpringSecurity提供的进行更新//第一个参数,是把我们当前的用户传入进行,第二个参数时密码,一般不放,我们自己处理,第三个是我们的权限列表UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());//实现更新,其实就是放入全局里面SecurityContextHolder.getContext().setAuthentication(authenticationToken);return RespBean.success("登录成功",tokenMap);}

(5)Mapper层

@Component
public interface AdminMapper extends BaseMapper<Admin> {Admin selectOne(QueryWrapper<Admin> username);
}

到现在你可以运行一下,看是不是出下面的错误

Description:Field passwordEncoder in com.xxxx.server.sevice.impl.IAdminServiceImpl required a bean of type 'org.springframework.security.crypto.password.PasswordEncoder' that could not be found.The injection point has the following annotations:- @org.springframework.beans.factory.annotation.Autowired(required=true)Action:Consider defining a bean of type 'org.springframework.security.crypto.password.PasswordEncoder' in your configuration.

原因是因为我们在编写我们的Service层的时候,里面有注入PasswordEncoder的时候,我们还没有提供,所有还会报错,慢慢的后续解决

5、退出登录和返回信息给前端

(1)首先实现思路

1、思路一

我们可以在SpringBoot里面,做相应的处理。这次不采用这种方式。

2、思路二

复习之前的思路

  • 登录之后返回token。
  • 前端会把token放在请求头
  • 访问任何的资源都会携带我们的token进行访问。
  • 然后我们去写一个拦截器,判断这个token是否合法有效的
    • 如果是有效的,就允许
    • 如果不对就错误

现在呢我们就和前端定义好,当你点退出登录的时候,我们返回退出成功,主要就是状态码200,拿到这个200后,前端把它的请求头中的token删除,再去调用就会被拦截。

(2)修改Controller编写


@RestController
@Api(tags = "LoginController")
public class LoginController {@Autowiredprivate IAdminService adminService;/*** 登录的请求* @param adminLoginParam* @param request* @return*/@ApiOperation(value = "登录之后返回token")@PostMapping("/login")public RespBean login(AdminLoginParam adminLoginParam, HttpServletRequest request) {return adminService.login(adminLoginParam.getUsername(),adminLoginParam.getPassword(),request);}/*** 退出登录的请求*/@ApiOperation(value = "退出登录")@PostMapping("/logout")public RespBean logout() {return RespBean.success("注销成功");}@ApiOperation(value = "获取当前登录用户信息")@GetMapping("/admin/info")public Admin getAdminInfo(Principal principal) {//这里讲一下Principal,这个是Springsecurity里面提供的,可以取对象的类,如果不知道,可以去学习一下SpringSecurity//其实刚才我们不是在编写登录方法的时候有了一个入池的操作嘛,然后我们这就可以用Principal来取if (null == principal) {return null;}String username = principal.getName();Admin admin = adminService.getAdminByUserName(username);//这里可以直接返回了,但是处于保护的情况下,设置一下admin.setPassword(null);return admin;}
}

(3)对Service进行修改

/*** 登录的服务类*/
public interface IAdminService extends IService<Admin> {/*** 登录之后返回token* @param username* @param password* @param request* @return* */RespBean login(String username, String password, HttpServletRequest request);/*** 根据用户名获取用户* @param username,名字* @return*/Admin getAdminByUserName(String username);
}
@Service
public class IAdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements IAdminService {@Autowiredprivate UserDetailsService userDetailsService;@AutowiredPasswordEncoder passwordEncoder;@AutowiredJwtTokenUtil jwtTokenUtil;@Value("${jwt.tokenHead")private String tokenHead;//头部信息@AutowiredAdminMapper adminMapper;/*** 登录之后返回token* @param username* @param password* @param request* @return*/@Overridepublic RespBean login(String username, String password, HttpServletRequest request) {//这里做一点说明,可能第一次做项目的人不是很理解,为什么这样搞//这里其实就是SpringSecurity给我提供的,如果不懂说明你SpringSecurity不行,可以去复习一下//其实就是我们编写的主类Admin实现了UserDetails和这个呼应起来,实现认证的流程UserDetails userDetails = userDetailsService.loadUserByUsername(username);if (null == userDetails || !passwordEncoder.matches(password,userDetails.getUsername())) {return RespBean.error("用户名或者密码不正确");}if (!userDetails.isEnabled()) {return RespBean.error("账号被禁用,请联系管理员");//其实这里有很多处理的,暂时这样了解}//如果上面的都通过了,说明没问题了,可以发放token令牌了String token = jwtTokenUtil.generateToken(userDetails);Map<String,String> tokenMap = new HashMap<>();tokenMap.put("token",token);//发放的tokentokenMap.put("tokenHead",tokenHead);//给前端的请求头,下次会带上//上面两步都完成了,我们编写token的时候,说了是要有时候有更新token的,我们用户也是会更新的//我们这里的更新可以用SpringSecurity提供的进行更新//第一个参数,是把我们当前的用户传入进行,第二个参数时密码,一般不放,我们自己处理,第三个是我们的权限列表UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());//实现更新,其实就是放入全局里面SecurityContextHolder.getContext().setAuthentication(authenticationToken);return RespBean.success("登录成功",tokenMap);}@Overridepublic Admin getAdminByUserName(String username) {//.eq("username",username)判断我们的用户是否匹配//.eq("enabled",true)判断是否用户被禁用return adminMapper.selectOne(new QueryWrapper<Admin>().eq("username",username).eq("enabled",true));}}

(4)Mapper层

mapper层不用改

6、进行Security过滤编写

(1)SecurityConfig配置

  • 按着步骤看
  • 不要先看,注入的东西,先去看方法,看到哪里有注入了,再去看注入的内容
package com.xxxx.server.config.security;import com.xxxx.server.pojo.Admin;
import com.xxxx.server.sevice.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.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetails;
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;@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {//这个配置,是SpringBoot里面的配置,如果不懂,你也不会来做项目了,哈哈哈@Autowiredprivate IAdminService adminService;@AutowiredJwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;//权限不足@AutowiredRestfulAccessDeniedHandler restfulAccessDeniedHandler;//未登录或者token失效@AutowiredRestAuthenticationEntryPoint restAuthenticationEntryPoint;/*** 第一步看这里* @return*/@Override//不应该加个Bean就可以了吗,为什么要加Override呢,这个问题留着@Beanpublic UserDetailsService userDetailsService() {return username -> {Admin admin = adminService.getAdminByUserName(username);//实现认证都是SpringSecurity自己完成了,但是我们这自己做了处理了,就自己来解释一下//验证会走我们自己的这里,密码的话会走下面configure(AuthenticationManagerBuilder auth)配置的的passwordEncoderif (null != admin) {return admin;}return null;};}/*** 第二步来看这* @param auth* @throws Exception*/@Overridepublic void configure(AuthenticationManagerBuilder auth) throws Exception {//我们自己重写了UserDetailsService,所以要编写这这里配置一下,密码是passwordEncoder来确定的,所以去注入一下auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());}@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}/*** 第三步才是最重要的配置了* @param http* @throws Exception*/@Overridepublic void configure(HttpSecurity http) throws Exception {//使用jwt,所以我们csrf肯定不要了,所以关闭http.csrf().disable()//使用token,所以session什么的都不用了,下面这两句话可以自己去搜索看看.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()//用and继续往下面配置.authorizeRequests()//允许登录的.antMatchers("/login","logout").permitAll()//表示上面的都可以不用验证而通过.anyRequest()//.anyRequest()和.authenticated()表示其他的要认证登录.authenticated().and().headers()//这个具体自己去百度一下,反正大概是禁缓存的.cacheControl();//添加jwt,登录授权过滤器,看下面的介绍,自己编写的一个http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);//未授权和未登录的返回结果http.exceptionHandling().accessDeniedHandler(restfulAccessDeniedHandler).authenticationEntryPoint(restAuthenticationEntryPoint);}
}

(2)自定义没权限的返回

package com.xxxx.server.config.security;import com.fasterxml.jackson.databind.ObjectMapper;
import com.xxxx.server.pojo.RespBean;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** 当访问接口没有权限时候,自定义返回结果*/
@Component
public class RestfulAccessDeniedHandler implements AccessDeniedHandler {@Overridepublic void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {httpServletResponse.setCharacterEncoding("UTF-8");httpServletResponse.setContentType("application/json");PrintWriter out = httpServletResponse.getWriter();RespBean bean = RespBean.error("权限不足,请联系管理员");bean.setCode(403);out.write(new ObjectMapper().writeValueAsString(bean));out.flush();out.close();}
}

(3)自定义未登录或者token失效返回页面

package com.xxxx.server.config.security;import com.fasterxml.jackson.databind.ObjectMapper;
import com.xxxx.server.pojo.RespBean;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;/*** 当未登录或者token失效时访问接口时,自定义返回结果*/
@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {//这个里面主要设置上面编码的呀,还有其他的response.setCharacterEncoding("UTF-8");response.setContentType("application/json");PrintWriter out = response.getWriter();RespBean respBean = RespBean.error("未登录,请登录");respBean.setCode(401);out.write(new ObjectMapper().writeValueAsString(respBean));//这个就是向前端写一点东西out.flush();out.close();}
}

(4)自定义登录的拦截器

package com.xxxx.server.config.security;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.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** 添加jwt,登录授权过滤器*/
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {@Value("${jwt.tokenHeader}")private String tokenHeader;@Value("${jwt.tokenHead}")private String tokenHead;@AutowiredJwtTokenUtil jwtTokenUtil;@Autowiredprivate UserDetailsService userDetailsService;//这个是个核心的方法,需要好好理解一下,但是我也不是很懂,自己各位去网上找一找,深入的理解一下吧@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {//前端传递内容的验证String authHeader = request.getHeader(tokenHeader);//这里是前端传给我们的Authentication//判断是否存在tokenif (null != authHeader && authHeader.startsWith(tokenHead)) {String authToken = authHeader.substring(tokenHead.length());//获取一下usernameString username = jwtTokenUtil.getUserNameFromToken(authToken);//token存在用户名,但是未登录if (null != username && null == SecurityContextHolder.getContext().getAuthentication()) {UserDetails userDetails = userDetailsService.loadUserByUsername(username);//相当于登录,这里就是使用了我们的自定义的UserDetailsService里面的方法//判断一下token是否有效if (jwtTokenUtil.validateToken(tokenHead,userDetails)) {UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails,"",userDetails.getAuthorities());//相当于重新设置一下,authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));SecurityContextHolder.getContext().setAuthentication(authenticationToken);}}}}
}

7、配置Swagger2

看另外一篇文章
https://blog.csdn.net/weixin_46635575/article/details/121460361

002云E办项目之登录模块相关推荐

  1. 2.vue3医疗在线问诊项目 - _登录模块 ==> 代码片段、css变量主题定制、cp-nav-bar组件封装、svg打包精灵图插件、cp-icon组件封装、表单校验、密码登录、短信验证码登录及两者

    2.医疗在线问诊项目 - _登录模块 ==> 代码片段.css变量主题定制.cp-nav-bar组件封装.svg打包精灵图插件.cp-icon组件封装.表单校验.密码登录.短信验证码登录及两者的 ...

  2. 云E办项目之部门管理

    文章目录 云E办---部门管理 一.展示所有部门 1. 后台接口及数据格式 2. 使用Element-ui中的Tree树形控件 3. 初始化部门信息 二. 添加部门 1. 后台接口及数据格式 2. 使 ...

  3. “浙里办“项目单点登录、埋点、二次回退的问题

    已经有一段时间没有更新博客了,因为最近变成了某个项目的负责人,就突然忙了起来. 刚接到这个项目的开始,我还觉得自己一定能很出色的完成这个任务.刚过了几天我就发现事情并不是我想象的那么简单,我要做的事情 ...

  4. 客户关系管理项目——用户登录模块设计

    一 模块需求细化 登录的用户,默认情况有三个不同角色,分别为:系统管理员,前台客服,信息管理员. 用户登录后能够根据其角色来进行相关工作,进行完工作需要能够注销. 细化需求如下: 用户登录之后按角色分 ...

  5. 【Java】云E办项目后端技术栈整合及代码阅读

    项目来源:Bilibili:带你从0搭建一个springboot+vue前后端分离的java项目 源码地址:https://github.com/Jimecc/yeb 本项目的后端部分我已经完整的部署 ...

  6. 【代码阅读】云E办项目后端技术栈总结及源码分析

    项目来源:Bilibili:带你从0搭建一个springboot+vue前后端分离的java项目 源码地址:https://github.com/Jimecc/yeb 本项目的后端部分我已经完整的部署 ...

  7. 亲测可用云e办项目的接口文档21年10月更新

    前言 一直想开发一个功能比较强大的项目,但是一直没有动手,最近终于有点时间来折腾它了.由于时隔两年没有接触前端了,所以需要一个小项目先练练手感.等这个项目完工之后在着手搞一个大工程.都说好记星不如烂笔 ...

  8. 云e办(后端)——项目介绍及搭载项目

    云e办 项目介绍 本项目目的是实现中小型企业的在线办公系统,云E办在线办公系统是一个用来管理日常的办公事务的一个系统,他能够管的内容有:日常的各种流程审批,新闻,通知,公告,文件信息,财务,人事,费用 ...

  9. vue项目云e办——登录页面(一)

    云e办 文章目录 云e办 视频学习地址 前端目标 效果 登录页面代码 视频学习地址 云e办视频学习地址 前端目标 表单可以校验是否为空,如果为空,点击登录时弹出错误提示框. 效果 登录页面代码 登录页 ...

最新文章

  1. 三个点在同一个半圆的概率_【国际数学竞赛】列方程求概率
  2. Python实现字符串反转的6种方法
  3. 【转】PBOC3.0和PBOC2.0标准规范异同分析
  4. java中jtansforms,java – 使用AffineTransform旋转图像
  5. 男朋友的回答可以多敷衍?
  6. 基线检查工具_最新版CAD燕秀工具箱2.87(支持20042021)
  7. Oracle 10g Audit(审计) --- 记录登录用户在Oracle中的所有操作(转)
  8. 设计模式之 里氏替换原则
  9. linux 高级i o函数,高级I/O函数
  10. VLFeat工具包在matlab使用方法
  11. java编写进行货币兑换_货币汇率java assignment
  12. 打游戏经常有人喷,刷个B站还是有?Python实现在网站上自动评论!键盘侠都喷不赢你!
  13. 将.bat文件设置为Window系统开机自启动项
  14. 【密码学/密码分析】基于TMTO的密码分析方法
  15. Autosar MCAL-SPI配置及使用
  16. 经纬高坐标系转到东北天坐标系
  17. ASCII码表和常见键盘码
  18. AutoCAD在指定布局中如何隐藏指定的图形?
  19. 怎么把图片转换成Tikz图片
  20. 把程序作为人生,把人生当作程序

热门文章

  1. 数据仓库系列——3.维度建模概述及案例
  2. 在线白板里面的协作工具有哪些
  3. 社交分享拼团持续走红 如何搭建自己的社交拼团平台?
  4. 牛逼哄哄的全链路监控系统!搭建起来也没有想象中的那么难啊...
  5. IDS比防火墙强,IPS你赞成吗?
  6. 计算机网络原理历年试题,自考计算机网络原理第一章历年试题汇总
  7. 电脑CPU使用率多少正常?
  8. Centos7 yum安装mysql(完整版)
  9. xxx is assigned a value but never used 报错
  10. 2022年华数杯数学建模A题环形振荡器的优化设计解题全过程文档及程序