1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 后端使用SpringBoot和Jwt工具与Redis数据库+前端Vue Element Admin实现用户携带token的登录功能案例

后端使用SpringBoot和Jwt工具与Redis数据库+前端Vue Element Admin实现用户携带token的登录功能案例

时间:2021-07-13 12:37:10

相关推荐

后端使用SpringBoot和Jwt工具与Redis数据库+前端Vue Element Admin实现用户携带token的登录功能案例

登录功能描述:

前端输入对应的用户信息 ,在用户输入邮箱后 点击发送按钮给邮箱发送验证码,拿取到验证填完之后,点击登录按钮给后端发送请求 ,后端接收到请求之后 ,第一步校验验证码,第二步校验用户名和密码是否正确,通过验证之后,表示登录成功,再给前端响应数据(之前返回的是登录用户,现在使用的是token,它是给返回的对象进行加密), 前端拿到后端响应的数据token, ,再次给后端发送请求,查询该用户的角色,前端拿取到用户的角色之后,根据角色的不同跳转到不同的页面;

前端页面:

1.前端基本 登录页面

<template><div class="login-container"><el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" autocomplete="on" label-position="left"><div class="title-container"><h3 class="title">登录</h3></div><el-form-item prop="username"><span class="svg-container"><svg-icon icon-class="user" /></span><el-inputref="username"v-model="loginForm.username"placeholder="Username"name="username"type="text"tabindex="1"autocomplete="on"/></el-form-item><el-tooltip v-model="capsTooltip" content="Caps lock is On" placement="right" manual><el-form-item prop="password"><span class="svg-container"><svg-icon icon-class="password" /></span><el-input:key="passwordType"ref="password"v-model="loginForm.password":type="passwordType"placeholder="Password"name="password"tabindex="2"autocomplete="on"@keyup.native="checkCapslock"@blur="capsTooltip = false"@keyup.enter.native="handleLogin"/><span class="show-pwd" @click="showPwd"><svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" /></span></el-form-item></el-tooltip><el-form-item prop="email"><span class="svg-container"><svg-icon icon-class="user" /></span><el-inputref="email"v-model="loginForm.email"placeholder="请输入邮箱"name="email"type="text"tabindex="3"style="width: 70%;"autocomplete="on"/><el-button type="primary" style="width:20%;" @click.native.prevent="sendEmail">发送</el-button></el-form-item><el-form-item prop="verifycode"><span class="svg-container"><svg-icon icon-class="user" /></span><el-inputref="verifycode"v-model="loginForm.verifycode"placeholder="请输入验证码"name="verifycode"type="text"tabindex="4"autocomplete="on"/></el-form-item><el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">登录</el-button><el-button type="primary" style="width:100%;margin-bottom:30px;margin-left: 0px;" @click="$router.push('/register')">注册</el-button><div style="position:relative"><div class="tips"><span>Username : admin</span><span>Password : any</span></div><div class="tips"><span style="margin-right:18px;">Username : editor</span><span>Password : any</span></div><el-button class="thirdparty-button" type="primary" @click="showDialog=true">Or connect with</el-button></div></el-form><el-dialog title="Or connect with" :visible.sync="showDialog">Can not be simulated on local, so please combine you own business simulation! ! !<br><br><br><social-sign /></el-dialog></div></template><script>import { validUsername } from '@/utils/validate'import {sendEmail} from '@/api/user'import SocialSign from './components/SocialSignin'export default {name: 'Login',components: { SocialSign },data() {const validateUsername = (rule, value, callback) => {if (!validUsername(value)) {callback(new Error('Please enter the correct user name'))} else {callback()}}const validatePassword = (rule, value, callback) => {if (value.length < 6) {callback(new Error('The password can not be less than 6 digits'))} else {callback()}}return {loginForm: {username: 'admin',password: '111111',email:'wangshan20010907@'},loginRules: {// username: [{ required: true, trigger: 'blur', validator: validateUsername }],// password: [{ required: true, trigger: 'blur', validator: validatePassword }]},passwordType: 'password',capsTooltip: false,loading: false,showDialog: false,redirect: undefined,otherQuery: {}}},watch: {$route: {handler: function(route) {const query = route.queryif (query) {this.redirect = query.redirectthis.otherQuery = this.getOtherQuery(query)}},immediate: true}},created() {// window.addEventListener('storage', this.afterQRScan)},mounted() {if (this.loginForm.username === '') {this.$refs.username.focus()} else if (this.loginForm.password === '') {this.$refs.password.focus()}},destroyed() {// window.removeEventListener('storage', this.afterQRScan)},methods: {//发送邮箱async sendEmail(){let {message}=await sendEmail(this.loginForm);this.$message.success(message);},checkCapslock(e) {const { key } = ethis.capsTooltip = key && key.length === 1 && (key >= 'A' && key <= 'Z')},showPwd() {if (this.passwordType === 'password') {this.passwordType = ''} else {this.passwordType = 'password'}this.$nextTick(() => {this.$refs.password.focus()})},handleLogin() {this.$refs.loginForm.validate(valid => {if (valid) {this.loading = truethis.$store.dispatch('user/login', this.loginForm).then((data) => {this.$router.push({ path: this.redirect || '/', query: this.otherQuery })this.loading = false}).catch((error) => {console.info('@/views/login:165',error)this.loading = false})} else {console.log('error submit!!')return false}})},getOtherQuery(query) {return Object.keys(query).reduce((acc, cur) => {if (cur !== 'redirect') {acc[cur] = query[cur]}return acc}, {})}// afterQRScan() {// if (e.key === 'x-admin-oauth-code') {//const code = getQueryObject(e.newValue)//const codeMap = {// wechat: 'code',// tencent: 'code'//}//const type = codeMap[this.auth_type]//const codeName = code[type]//if (codeName) {// this.$store.dispatch('LoginByThirdparty', codeName).then(() => {// this.$router.push({ path: this.redirect || '/' })// })//} else {// alert('第三方登录失败')//}// }// }}}</script><style lang="scss">/* 修复input 背景不协调 和光标变色 *//* Detail see /PanJiaChen/vue-element-admin/pull/927 */$bg:#283443;$light_gray:#fff;$cursor: #fff;@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {.login-container .el-input input {color: $cursor;}}/* reset element-ui css */.login-container {.el-input {display: inline-block;height: 47px;width: 85%;input {background: transparent;border: 0px;-webkit-appearance: none;border-radius: 0px;padding: 12px 5px 12px 15px;color: $light_gray;height: 47px;caret-color: $cursor;&:-webkit-autofill {box-shadow: 0 0 0px 1000px $bg inset !important;-webkit-text-fill-color: $cursor !important;}}}.el-form-item {border: 1px solid rgba(255, 255, 255, 0.1);background: rgba(0, 0, 0, 0.1);border-radius: 5px;color: #454545;}}</style><style lang="scss" scoped>$bg:#2d3a4b;$dark_gray:#889aa4;$light_gray:#eee;.login-container {min-height: 100%;width: 100%;background-color: $bg;overflow: hidden;.login-form {position: relative;width: 520px;max-width: 100%;padding: 160px 35px 0;margin: 0 auto;overflow: hidden;}.tips {font-size: 14px;color: #fff;margin-bottom: 10px;span {&:first-of-type {margin-right: 16px;}}}.svg-container {padding: 6px 5px 6px 15px;color: $dark_gray;vertical-align: middle;width: 30px;display: inline-block;}.title-container {position: relative;.title {font-size: 26px;color: $light_gray;margin: 0px auto 40px auto;text-align: center;font-weight: bold;}}.show-pwd {position: absolute;right: 10px;top: 7px;font-size: 16px;color: $dark_gray;cursor: pointer;user-select: none;}.thirdparty-button {position: absolute;right: 0;bottom: 6px;}@media only screen and (max-width: 470px) {.thirdparty-button {display: none;}}}</style>

2.登录页面的路由配置

3.修改框架模拟的路径 换成我们自己的后端逻辑

vue 可以自动生成这些代码 .注意的地方都标注出来了

后端:

1.子类pom文件依赖

<dependencies><!--web起步依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- nacos 服务发现 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--swagger2--><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId></dependency><!-- feign 远程调用 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--测试--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId></dependency><!-- mybatis plus--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>${mybatis.plus.version}</version></dependency><!-- mysql驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--自定义项目--><dependency><groupId>com.czxy</groupId><artifactId>zx_common01</artifactId></dependency><dependency><groupId>com.czxy</groupId><artifactId>zx_domain01</artifactId></dependency><!-- redis 启动器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><!-- JavaMail 启动器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mail</artifactId></dependency><!-- MQ 启动器 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><!-- fastjson --><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId></dependency><!--JavaBean工具类,用于JavaBean数据封装--><dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId></dependency><!--jwt工具--><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId></dependency><!--joda 时间工具类 --><dependency><groupId>joda-time</groupId><artifactId>joda-time</artifactId></dependency></dependencies>

application.yml

# 服务端口号server:port: 9010# 服务名spring:application:name: user-servicedatasource:driverClassName: com.mysql.jdbc.Driverurl: jdbc:mysql://127.0.0.1:3306/zx_edu_user?useUnicode=true&characterEncoding=utf8username: rootpassword: rootdruid: #druid 连接池配置initial-size: 1 #初始化连接池大小min-idle: 1 #最小连接数max-active: 20 #最大连接数test-on-borrow: true #获取连接时候验证,会影响性能cloud:nacos:discovery:server-addr: 127.0.0.1:8848 #nacos服务地址redis:database: 0 #数据库索引,取值0-15,表示16个库可选择host: 127.0.0.1 #服务器地址port: 6379 #服务器连接端口号mail:host: #发送邮件服务器username: wangshan20010907@ #账号password: IBCEGYGFTZMQFFQY#授权密码default-encoding: UTF-8#默认编码时rabbitmq:host: 127.0.0.1port: 5672username: guestpassowrd: guestvirtualHost: /freemarker:cache: false #页面不加载缓存,修改即时生效#开启log4j打印SQL语句logging:level:com:czxy:zx:user:mapper: debug# mp日志打印mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:db-config:logic-delete-value: 1logic-not-delete-value: 0sc:jwt:secret: sc@Login(Auth}*^31)&czxy% # 登录校验的密钥pubKeyPath: D:/rsa/rsa.pub # 公钥地址priKeyPath: D:/rsa/rsa.pri # 私钥地址expire: 360 # 过期时间,单位分钟

3.配置类utils:

验证码VerifyCodeUtils:

package com.czxy.zx.utils;import com.czxy.zx.vo.VerifyCode;import java.awt.*;import java.awt.image.BufferedImage;import java.util.Random;public class VerifyCodeUtils {//获取验证码public static VerifyCode getVerifyCode(){VerifyCode verifyCode = new VerifyCode();//字体只显示大写,去掉了1,0,i,o几个容易混淆的字符String VERIFY_CODES = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";int IMG_WIDTH = 72;int IMG_HEIGTH = 27;Random random = new Random();//创建图片BufferedImage image = new BufferedImage(IMG_WIDTH, IMG_HEIGTH, BufferedImage.TYPE_INT_RGB);//画板Graphics g = image.getGraphics();//填充背景g.setColor(Color.WHITE);g.fillRect(1,1,IMG_WIDTH-2,IMG_HEIGTH-2);g.setFont(new Font("楷体",Font.BOLD,25));StringBuilder sb = new StringBuilder();//写字for(int i = 1 ; i <= 4 ; i ++){//随机颜色g.setColor(new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));int len = random.nextInt(VERIFY_CODES.length());String str = VERIFY_CODES.substring(len,len+1);sb.append(str);g.drawString(str, IMG_WIDTH / 6 * i , 22 );}// 生成随机干扰线for (int i = 0; i < 30; i++) {//随机颜色g.setColor(new Color(random.nextInt(255),random.nextInt(255),random.nextInt(255)));int x = random.nextInt(IMG_WIDTH - 1);int y = random.nextInt(IMG_HEIGTH - 1);int x1 = random.nextInt(12) + 1;int y1 = random.nextInt(6) + 1;g.drawLine(x, y, x - x1, y - y1);}verifyCode.setCode(sb.toString());verifyCode.setImage(image);verifyCode.setType("jpeg");return verifyCode;}}

JwtUtils类:

package com.czxy.zx.utils;import io.jsonwebtoken.Claims;import io.jsonwebtoken.JwtBuilder;import io.jsonwebtoken.Jwts;import io.jsonwebtoken.SignatureAlgorithm;import mons.beanutils.BeanUtils;import org.joda.time.DateTime;import java.beans.BeanInfo;import java.beans.Introspector;import java.beans.PropertyDescriptor;import java.security.PrivateKey;import java.security.PublicKey;/*** Created by wangshan.*/public class JwtUtils {/*** 私钥加密token* @param data 需要加密的数据(载荷内容)* @param expireMinutes 过期时间,单位:分钟* @param privateKey 私钥* @return*/public static String generateToken(Object data, int expireMinutes, PrivateKey privateKey) {try {//1 获得jwt构建对象JwtBuilder jwtBuilder = Jwts.builder();//2 设置数据if( data == null ) {throw new RuntimeException("数据不能为空");}BeanInfo beanInfo = Introspector.getBeanInfo(data.getClass());PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {// 获得属性名String name = propertyDescriptor.getName();// 获得属性值Object value = propertyDescriptor.getReadMethod().invoke(data);if(value != null) {jwtBuilder.claim(name,value);}}//3 设置过期时间jwtBuilder.setExpiration(DateTime.now().plusMinutes(expireMinutes).toDate());//4 设置加密jwtBuilder.signWith(SignatureAlgorithm.RS256, privateKey);//5 构建return pact();} catch (Exception e) {throw new RuntimeException(e);}}/*** 通过公钥解析token* @param token 需要解析的数据* @param publicKey 公钥* @param beanClass 封装的JavaBean* @return* @throws Exception*/public static <T> T getObjectFromToken(String token, PublicKey publicKey,Class<T> beanClass) throws Exception {//1 获得解析后内容Claims body = Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token).getBody();//2 将内容封装到对象JavaBeanT bean = beanClass.newInstance();BeanInfo beanInfo = Introspector.getBeanInfo(beanClass);PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {// 获得属性名String name = propertyDescriptor.getName();// 通过属性名,获得对应解析的数据Object value = body.get(name);if(value != null) {// 将获得的数据封装到对应的JavaBean中BeanUtils.setProperty(bean,name,value);}}return bean;}}

RsaUtils类

package com.czxy.zx.utils;import java.io.File;import java.io.IOException;import java.nio.file.Files;import java.security.*;import java.security.spec.PKCS8EncodedKeySpec;import java.security.spec.X509EncodedKeySpec;/*** Created by wangshan.*/public class RsaUtils {/*** 从文件中读取公钥** @param filename 公钥保存路径,相对于classpath* @return 公钥对象* @throws Exception*/public static PublicKey getPublicKey(String filename) throws Exception {byte[] bytes = readFile(filename);return getPublicKey(bytes);}/*** 从文件中读取密钥** @param filename 私钥保存路径,相对于classpath* @return 私钥对象* @throws Exception*/public static PrivateKey getPrivateKey(String filename) throws Exception {byte[] bytes = readFile(filename);return getPrivateKey(bytes);}/*** 获取公钥** @param bytes 公钥的字节形式* @return* @throws Exception*/public static PublicKey getPublicKey(byte[] bytes) throws Exception {X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);KeyFactory factory = KeyFactory.getInstance("RSA");return factory.generatePublic(spec);}/*** 获取密钥** @param bytes 私钥的字节形式* @return* @throws Exception*/public static PrivateKey getPrivateKey(byte[] bytes) throws Exception {PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);KeyFactory factory = KeyFactory.getInstance("RSA");return factory.generatePrivate(spec);}/*** 根据密文,生存rsa公钥和私钥,并写入指定文件** @param publicKeyFilename 公钥文件路径* @param privateKeyFilename 私钥文件路径* @param secret 生成密钥的密文* @throws Exception*/public static void generateKey(String publicKeyFilename, String privateKeyFilename, String secret) throws Exception {KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");SecureRandom secureRandom = new SecureRandom(secret.getBytes());keyPairGenerator.initialize(1024, secureRandom);KeyPair keyPair = keyPairGenerator.genKeyPair();// 获取公钥并写出byte[] publicKeyBytes = keyPair.getPublic().getEncoded();writeFile(publicKeyFilename, publicKeyBytes);// 获取私钥并写出byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();writeFile(privateKeyFilename, privateKeyBytes);}private static byte[] readFile(String fileName) throws Exception {return Files.readAllBytes(new File(fileName).toPath());}private static void writeFile(String destPath, byte[] bytes) throws IOException {File dest = new File(destPath);//创建父文件夹if(!dest.getParentFile().exists()){dest.getParentFile().mkdirs();}//创建需要的文件if (!dest.exists()) {dest.createNewFile();}Files.write(dest.toPath(), bytes);}}

3.配置类config:

JwtProperties :

package com.czxy.zx.user.config;import com.czxy.zx.utils.RsaUtils;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Configuration;import javax.annotation.PostConstruct;import java.io.File;import java.security.PrivateKey;import java.security.PublicKey;@Configuration@ConfigurationProperties(prefix = "sc.jwt")@Datapublic class JwtProperties {private String secret;private String pubKeyPath;private String priKeyPath;private Integer expire;private PublicKey publicKey;private PrivateKey privateKey;@PostConstruct//初始化方法注解public void init() {try {File pubFile = new File(pubKeyPath);File priFile = new File(priKeyPath);if(!pubFile.exists() || ! priFile.exists()) {RsaUtils.generateKey(pubKeyPath,priKeyPath,secret);}// 获得公钥和私钥对象this.publicKey = RsaUtils.getPublicKey(pubKeyPath);this.privateKey = RsaUtils.getPrivateKey(priKeyPath);} catch (Exception e) {e.printStackTrace();}}}

MyBatisPlusConfig :

package com.czxy.zx.user.config;import com.baomidou.mybatisplus.annotation.DbType;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;import org.springframework.context.annotation.Bean;import org.ponent;@Componentpublic class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return mybatisPlusInterceptor;}}

免前端页面测试:

Swagger2ConfigurationV3

package com.czxy.zx.user.config;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;/*** Swagger2 配置类,* 访问路径:swagger-ui.html* 自动注册:*位置:resources/META-INF/spring.factories*内容:* org.springframework.boot.autoconfigure.EnableAutoConfiguration=\*com.czxy.changgou4.config.Swagger2Configuration*/@Configuration@EnableSwagger2public class Swagger2ConfigurationV3 {@Beanpublic Docket createRestApi() {// 1 确定文档Swagger版本Docket docket = new Docket(DocumentationType.SWAGGER_2);// 2 设置 api基本信息docket.apiInfo(apiInfo());// 3 设置自定义加载路径docket = docket.select().apis(RequestHandlerSelectors.basePackage("com.czxy")).paths(PathSelectors.any()).build();//4 设置权限docket.securitySchemes(securitySchemes());docket.securityContexts(securityContexts());return docket;}private ApiInfo apiInfo() {return new ApiInfoBuilder().title("API").description("基于swagger接口文档").contact(new Contact("java34","","liangtong@")).version("1.0").build();}private List<ApiKey> securitySchemes() {List<ApiKey> list = new ArrayList<>();// name 为参数名 keyname是页面传值显示的 keyname, name在swagger鉴权中使用list.add(new ApiKey("Authorization", "Authorization", "header"));return list;}private List<SecurityContext> securityContexts() {List<SecurityContext> list = new ArrayList<>();list.add(SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.regex("^(?!auth).*$")).build());return list;}private List<SecurityReference> defaultAuth() {AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];authorizationScopes[0] = authorizationScope;List<SecurityReference> list = new ArrayList();list.add(new SecurityReference("Authorization", authorizationScopes));return list;}}

队列的配置类:

RabbitEmailConfig

package com.czxy.zx.user.config;import org.springframework.amqp.core.Queue;import org.springframework.context.annotation.Bean;import org.ponent;@Componentpublic class RabbitEmailConfig {//队列名称public static final String QUEUE_LOGIN_EMAIL="login_email";public static final String QUEUE_REGISTER_EMAIL="register_email";//生成队列对象@Bean(QUEUE_LOGIN_EMAIL)public Queue queue(){return new Queue(QUEUE_LOGIN_EMAIL);}//生成队列对象@Bean(QUEUE_REGISTER_EMAIL)public Queue queue2(){return new Queue(QUEUE_REGISTER_EMAIL);}}

登录service:

package com.czxy.zx.user.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.czxy.zx.domain.EduUser;import com.czxy.zx.exception.EduException;import com.czxy.zx.user.mapper.EduUserMapper;import com.czxy.zx.user.service.EduUserService;import mons.lang.StringUtils;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;import java.util.Date;import java.util.List;@Service@Transactionalpublic class EduUserServiceImpl extends ServiceImpl<EduUserMapper, EduUser> implements EduUserService {@Overridepublic boolean register(EduUser user) {QueryWrapper<EduUser> queryWrapper = new QueryWrapper<>();queryWrapper.eq("username",user.getUsername());EduUser selectOne = baseMapper.selectOne(queryWrapper);if(selectOne!=null){//用户已注册throw new EduException("该用户名已经存在啦");}user.setStatus("0");user.setCreated(new Date());int insert = baseMapper.insert(user);return insert==1;}@Overridepublic EduUser login(EduUser user) {QueryWrapper<EduUser> queryWrapper = new QueryWrapper<>();queryWrapper.eq(StringUtils.isNotBlank(user.getUsername()),"username",user.getUsername());queryWrapper.eq(StringUtils.isNotBlank(user.getPassword()),"password",user.getPassword());List<EduUser> list = baseMapper.selectList(queryWrapper);if(list.size()>0){//在数据找到return list.get(0);}return null;}}

登录controller层:

package com.czxy.zx.user.controller;import com.alibaba.fastjson.JSONObject;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.czxy.zx.domain.EduUser;import com.czxy.zx.user.config.JwtProperties;import com.czxy.zx.user.config.RabbitEmailConfig;import com.czxy.zx.user.service.EduUserService;import com.czxy.zx.utils.JwtUtils;import com.czxy.zx.vo.BaseResult;import com.czxy.zx.vo.UserEmail;import com.google.gson.JsonObject;import mons.lang.StringUtils;import org.springframework.amqp.rabbit.core.RabbitTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;import java.util.*;import java.util.concurrent.TimeUnit;@RestController@RequestMapping("/user")public class EduUserController {//redis相关实体类@Resourceprivate StringRedisTemplate stringRedisTemplate;//mq消息队列的实体类@Resourceprivate RabbitTemplate rabbitTemplate;@Resourceprivate EduUserService eduUserService;@Resourceprivate JwtProperties jwtProperties;@GetMapping("/info")public BaseResult getInfo(String token) {System.out.println("info-->"+token);Map<String,Object> map = new HashMap<>();try {//使用jwt工具解析token得到用户, 获取用户的角色EduUser user = JwtUtils.getObjectFromToken(token, jwtProperties.getPublicKey(), EduUser.class);System.out.println("user = "+user);if(user.getRoles()!=null){map.put("roles", user.getRoles().split(","));}else {//为普通用户map.put("roles",Arrays.asList("editor"));}map.put("avatar", "/f778738c-e4f8-4870-b634-56703b4acafe.gif");map.put("name",user.getUsername());} catch (Exception e) {e.printStackTrace();return BaseResult.error("获取用户角色失败");}System.out.println(map);return BaseResult.ok("登录成功",map);}@GetMapping("/logOut")public BaseResult logOut(){return BaseResult.ok("退出成功啦~");}@GetMapping("/active")public BaseResult active(String uuid){//1.从redis中获取该uuid 对应的用户名username,并从redis中删除String username = stringRedisTemplate.opsForValue().get(uuid);//2.校验// username==nullif(username==null){return BaseResult.error("超出激活时间, 或该用户已经成功激活");}//username如果存在 则去数据库中根据用户名获取该用户信息QueryWrapper<EduUser> queryWrapper = new QueryWrapper<>();queryWrapper.eq("username",username);EduUser one = eduUserService.getOne(queryWrapper);//判断如果不存在该用户 则给出提示if(one==null){return BaseResult.error("该用户不存在");}//否则判断该用户是否要激活 1(激活过) 0(未激活)if(!"0".equalsIgnoreCase(one.getStatus())){return BaseResult.error("该用户已经激活过,无需再次激活");}//修改状态one.setStatus("1");eduUserService.updateById(one);stringRedisTemplate.delete(uuid);return BaseResult.ok("修改成功");}@PostMapping("/register")public BaseResult register(@RequestBody EduUser user){//先校验验证码是否正确String vsCode = stringRedisTemplate.opsForValue().get("register_" + user.getUsername());stringRedisTemplate.delete("register_"+user.getUsername());if(vsCode==null){return BaseResult.error("验证码已经失效l ");}if(!vsCode.equalsIgnoreCase(user.getVerifycode())){return BaseResult.error("验证码错误");}boolean rel = eduUserService.register(user);if(rel){//成功 则随机生成一个uuid 并发送邮箱 需要用户激活String uuid = UUID.randomUUID().toString().replaceAll("-", "");stringRedisTemplate.opsForValue().set(uuid,user.getUsername(),50, TimeUnit.MINUTES);// String url="http://localhost:19528/#/active?uuid="+uuid;String url="<a href='http://localhost:19528/#/active?uuid="+uuid+"'>点击激活<a/>";String text=user.getUsername()+" 你好,您在使用本站的激活程序,请点击 "+url+" 进行激活";//拼装路径UserEmail userEmail = new UserEmail();userEmail.setUsername(user.getUsername());userEmail.setText(text);userEmail.setEmail(user.getEmail());//存放在消息队列中String s = JSONObject.toJSONString(userEmail);rabbitTemplate.convertAndSend(RabbitEmailConfig.QUEUE_REGISTER_EMAIL,s);return BaseResult.ok("注册成功,去登录");}else {return BaseResult.error("注册失败啦,");}}@PostMapping("/login")public BaseResult login(@RequestBody EduUser user){//1.校验验证码//获取验证码String vsCode = stringRedisTemplate.opsForValue().get("login_" + user.getUsername());// 删除redis中的一次性验证码stringRedisTemplate.delete("login_"+user.getUsername());if(vsCode==null){return BaseResult.error("验证码失效了");}if (!user.getVerifycode().equalsIgnoreCase(vsCode)){return BaseResult.error("验证码错误");}//校验用户名和密码是否正确EduUser loginU = eduUserService.login(user);if(loginU!=null){//String token="admin-token";EduUser lu = new EduUser();//把当前用户非敏感信息作为token发送给前端lu.setRoles(loginU.getRoles());lu.setUsername(loginU.getUsername());String token = JwtUtils.generateToken(lu, jwtProperties.getExpire(), jwtProperties.getPrivateKey());System.out.println("token= "+token);return BaseResult.ok("登录成功").append("token",token);}else {return BaseResult.error("用户名或者密码错误,登录失败");}}@PostMapping("/sendEmail")public BaseResult sendEmail(@RequestBody EduUser user){//生成四位数的验证码int number = new Random().nextInt(8999) + 1000;//存入redis数据库中stringRedisTemplate.opsForValue().set("login_"+user.getUsername(),number+"");UserEmail userEmail = new UserEmail();userEmail.setUsername(user.getUsername());userEmail.setEmail(user.getEmail());userEmail.setText("登录密码是:"+number);//把验证码发送到消息队列中String s = JSONObject.toJSONString(userEmail);rabbitTemplate.convertAndSend(RabbitEmailConfig.QUEUE_LOGIN_EMAIL,s);return BaseResult.ok("邮件发送中,请注意查阅");}}

package com.czxy.zx.user.handler;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;import org.apache.ibatis.reflection.MetaObject;import org.ponent;import java.util.Date;@Componentpublic class EduHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {this.setFieldValByName("created",new Date(),metaObject);}@Overridepublic void updateFill(MetaObject metaObject) {this.setFieldValByName("created",new Date(),metaObject);}}

验证码controller层:

package com.czxy.zx.user.controller;import com.czxy.zx.utils.VerifyCodeUtils;import com.czxy.zx.vo.BaseResult;import com.czxy.zx.vo.VerifyCode;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;import javax.imageio.ImageIO;import javax.servlet.http.HttpServletResponse;import java.io.IOException;@RestController@RequestMapping("/verifyCode")public class VerifyCodeController {@Resourceprivate StringRedisTemplate stringRedisTemplate;@GetMapping("/{username}")public void getVerifyCode(@PathVariable("username") String username, HttpServletResponse response) throws IOException {VerifyCode verifyCode = VerifyCodeUtils.getVerifyCode();stringRedisTemplate.opsForValue().set("register_"+username,verifyCode.getCode());//给前端响应图片ImageIO.write(verifyCode.getImage(),verifyCode.getType(),response.getOutputStream());}}

EduUser

package com.czxy.zx.domain;import com.baomidou.mybatisplus.annotation.*;import io.swagger.annotations.ApiModel;import lombok.Data;import java.util.Date;/****/@Data@TableName("edu_user")@ApiModel(value = "EduUser对象",description = "用户")public class EduUser {@TableId(value="id" , type = IdType.AUTO)private Integer id;//用户名private String username;//用户密码private String password;//电话private String phone;//邮箱private String email;//角色,多个值使用逗号分隔,例如:admin,editorprivate String roles;//创建时间@TableField(value = "created",fill = FieldFill.INSERT)private Date created;//状态:0 未激活、1已激活private String status;@TableField(exist = false)private String verifycode;@TableField(exist = false)private String repassword;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。