Browse Source

初始版本

李云瑞 1 month ago
parent
commit
2ec39d63ef

+ 26 - 0
pom.xml

@@ -81,6 +81,32 @@
             <artifactId>spring-boot-starter-test</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>1.2.83</version>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.security</groupId>
+            <artifactId>spring-security-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-mail</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-validation</artifactId>
+        </dependency>
     </dependencies>
 
     <build>

+ 121 - 0
src/main/java/com/example/springboot/config/SecurityConfiguration.java

@@ -0,0 +1,121 @@
+package com.example.springboot.config;
+
+
+import com.alibaba.fastjson.JSONObject;
+import com.example.springboot.entity.RestBean;
+import com.example.springboot.service.AuthorizeService;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+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.EnableWebSecurity;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
+import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.CorsConfigurationSource;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.sql.DataSource;
+import java.io.IOException;
+
+@Configuration
+@EnableWebSecurity
+public class SecurityConfiguration {
+
+    @Resource
+    AuthorizeService authorizeService;
+
+    @Resource
+    DataSource dataSource;
+
+    @Bean
+    public SecurityFilterChain filterChain(HttpSecurity http,
+                                           PersistentTokenRepository repository) throws Exception {
+        return http
+                .authorizeHttpRequests()
+                .antMatchers("/api/auth/**","/api/user/**","/api/**").permitAll()
+                .anyRequest().authenticated()
+                .and()
+                .formLogin()
+                .loginProcessingUrl("/api/auth/login")
+                .successHandler(this::onAuthenticationSuccess)
+                .failureHandler(this::onAuthenticationFailure)
+                .and()
+                .logout()
+                .logoutUrl("/api/auth/logout")
+                .logoutSuccessHandler(this::onAuthenticationSuccess)
+                .and()
+                .rememberMe()
+                .rememberMeParameter("remember")
+                .tokenRepository(repository)
+                .tokenValiditySeconds(3600 * 24 * 7)
+                .and()
+                .csrf()
+                .disable()
+                .cors()
+                .configurationSource(corsConfigurationSource())
+                .and()
+                .exceptionHandling()
+                .authenticationEntryPoint(this::onAuthenticationFailure)
+                .and()
+                .build();
+    }
+
+    @Bean
+    public PersistentTokenRepository tokenRepository(){
+        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
+        jdbcTokenRepository.setDataSource(dataSource);
+        jdbcTokenRepository.setCreateTableOnStartup(false);
+        return jdbcTokenRepository;
+    }
+
+    /*
+     * 解决跨域问题
+     * */
+    public CorsConfigurationSource corsConfigurationSource() {
+        CorsConfiguration config = new CorsConfiguration();//1. 添加 CORS配置信息
+        config.addAllowedOriginPattern("*");//放行哪些原始域
+        config.setAllowCredentials(true);//是否发送 Cookie
+        config.addAllowedMethod("*");//放行哪些请求方式
+        config.addAllowedHeader("*");//放行哪些原始请求头部信息
+        config.addExposedHeader("*");//暴露哪些头部信息
+        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();//2. 添加映射路径
+        corsConfigurationSource.registerCorsConfiguration("/**",config);
+        return corsConfigurationSource;
+    }
+
+    @Bean
+    public AuthenticationManager authenticationManager(HttpSecurity security) throws Exception {
+        return security
+                .getSharedObject(AuthenticationManagerBuilder.class)
+                .userDetailsService(authorizeService)
+                .and().build();
+    }
+
+    @Bean
+    public BCryptPasswordEncoder passwordEncoder(){
+        return new BCryptPasswordEncoder();
+    }
+
+    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse response, org.springframework.security.core.Authentication authentication) throws IOException {
+        response.setCharacterEncoding("utf-8");
+        if (httpServletRequest.getRequestURI().endsWith("/login"))
+            response.getWriter().write(JSONObject.toJSONString(RestBean.success("登录成功")));
+        else if (httpServletRequest.getRequestURI().endsWith("/logout"))
+            response.getWriter().write(JSONObject.toJSONString(RestBean.success("退出登录成功")));
+    }
+
+    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
+        response.setCharacterEncoding("utf-8");
+        response.getWriter().write(JSONObject.toJSONString(RestBean.failure(401,exception.getMessage())));
+    }
+
+
+}

+ 95 - 0
src/main/java/com/example/springboot/controller/AuthorizeController.java

@@ -0,0 +1,95 @@
+package com.example.springboot.controller;
+
+import com.example.springboot.entity.RestBean;
+import com.example.springboot.service.AuthorizeService;
+import org.hibernate.validator.constraints.Length;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpSession;
+import javax.validation.constraints.Pattern;
+
+@Validated
+@RestController
+@RequestMapping("/api/auth")
+public class AuthorizeController {
+    private final String EMAIL_REGEXP = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$";
+    private final String USERNAME_REGEXP = "^[a-zA-Z0-9\\u4E00-\\u9FA5]+$";
+
+    @Resource
+    AuthorizeService service;
+
+    /*
+     * 新用户注册发送邮箱验证码
+     * */
+    @PostMapping("/valid-register-email")
+    public RestBean<String> validRegisterEmail(@Pattern(regexp = EMAIL_REGEXP)@RequestParam("email") String email,
+                                               HttpSession session){
+        String str = service.sendValidateEmail(email,session.getId(), false);
+        if (str == null)
+            return RestBean.success("邮件发送成功,请注意查收");
+        else
+            return RestBean.failure(400,str);
+    }
+
+    /*
+     * 用户忘记密码发送邮箱验证码
+     * */
+    @PostMapping("/valid-reset-email")
+    public RestBean<String> validResetEmail(@Pattern(regexp = EMAIL_REGEXP)@RequestParam("email") String email,
+                                            HttpSession session){
+        String str = service.sendValidateEmail(email,session.getId(), true);
+        if (str == null)
+            return RestBean.success("邮件发送成功,请注意查收");
+        else
+            return RestBean.failure(400,str);
+    }
+
+    /*
+     * 新用户注册
+     * */
+    @PostMapping("/register")
+    public RestBean<String> registerUser(@Pattern(regexp = USERNAME_REGEXP) @Length(min = 2,max = 8) @RequestParam("username") String userName,
+                                         @Length(min = 6, max = 16) @RequestParam("password") String password,
+                                         @Pattern(regexp = EMAIL_REGEXP) @RequestParam("email") String email,
+                                         @Length(min = 6, max = 6) @RequestParam("code") String code,
+                                         HttpSession session) {
+        String str = service.vaildateAndRegister(userName, password, email, code, session.getId());
+        if (str == null){
+            return RestBean.success("注册成功,请前往登录页面进行登录");
+        } else {
+            return RestBean.failure(400,str);
+        }
+    }
+
+    @PostMapping("/start-reset")
+    public RestBean<String> startReset(@Pattern(regexp = EMAIL_REGEXP) @RequestParam("email") String email,
+                                       @Length(min = 6, max = 6) @RequestParam("code") String code,
+                                       HttpSession session) {
+        String str = service.vaildateOnly(email, code, session.getId());
+        if (str == null){
+            session.setAttribute("reset-password", email);
+            return RestBean.success();
+        } else {
+            return RestBean.failure(400, str);
+        }
+    }
+    @PostMapping("/do-reset")
+    public RestBean<String> ResetPassword(@Length(min = 6, max = 16) @RequestParam("password") String password,
+                                          HttpSession session) {
+        String email = (String) session.getAttribute("reset-password");
+        if (email == null){
+            return RestBean.failure(400,"请先完成邮箱验证");
+        } else if (service.resetPassword(password,email)){
+            session.removeAttribute("reset-password");
+            return RestBean.success("密码重置成功");
+        } else {
+            return RestBean.failure(500,"内部错误,请联系管理员");
+        }
+    }
+
+}

+ 21 - 2
src/main/java/com/example/springboot/controller/UserController.java

@@ -3,21 +3,31 @@ package com.example.springboot.controller;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import com.example.springboot.entity.User;
+import com.example.springboot.entity.Auth.User;
+import com.example.springboot.entity.RestBean;
+import com.example.springboot.entity.User.AccountUser;
 import com.example.springboot.service.UserService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import javax.servlet.http.HttpSession;
 import java.util.List;
 
 @RestController
-@RequestMapping("/user")
+@RequestMapping("api/user")
 public class UserController {
 
 
     @Autowired
     UserService userService;
 
+    @GetMapping("/me")
+//    public RestBean<AccountUser> me(@SessionAttribute("account") AccountUser user){
+    public RestBean<AccountUser> me(HttpSession session, AccountUser user){
+        return RestBean.success(user);
+    }
+
+
     //查询所用用户
     @GetMapping("/queryList")
     public List<User> queryList() {
@@ -58,6 +68,7 @@ public class UserController {
                                 @RequestParam(defaultValue = "") String phone) {
         IPage<User> page = new Page<>(pageNum,pageSize);
         QueryWrapper<User> queryWrapper = new QueryWrapper<>();
+        System.out.println("111111111111");
         if(!"".equals(name)){
             queryWrapper.like("name",name);
         }
@@ -66,4 +77,12 @@ public class UserController {
         }
         return userService.page(page,queryWrapper);
     }
+    @GetMapping("/page2")
+    public IPage<User> findPage(){
+        int pageNum = 1;
+        int pageSize = 10;
+        IPage<User> page = new Page<>(pageNum,pageSize);
+        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
+        return userService.page(page,queryWrapper);
+    }
 }

+ 13 - 0
src/main/java/com/example/springboot/entity/Auth/Account.java

@@ -0,0 +1,13 @@
+package com.example.springboot.entity.Auth;
+
+import lombok.Data;
+
+@Data
+public class Account {
+
+    int id;
+    String username;
+    String email;
+    String password;
+
+}

+ 1 - 1
src/main/java/com/example/springboot/entity/User.java → src/main/java/com/example/springboot/entity/Auth/User.java

@@ -1,4 +1,4 @@
-package com.example.springboot.entity;
+package com.example.springboot.entity.Auth;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import lombok.Data;

+ 34 - 0
src/main/java/com/example/springboot/entity/RestBean.java

@@ -0,0 +1,34 @@
+package com.example.springboot.entity;
+
+import lombok.Data;
+
+@Data
+public class RestBean<T> {
+
+    private int status;
+    private boolean success;
+    private T message;
+
+    public RestBean(int status, boolean success, T message) {
+        this.status = status;
+        this.success = success;
+        this.message = message;
+    }
+
+    public static <T> RestBean<T> success(){
+        return new RestBean<>(200,true,null);
+    }
+
+    public static <T> RestBean<T> success(T data){
+        return new RestBean<>(200,true,data);
+    }
+
+    public static <T> RestBean<T> failure(int status){
+        return new RestBean<>(status,false,null);
+    }
+
+    public static <T> RestBean<T> failure(int status,T data){
+        return new RestBean<>(status,false,data);
+    }
+
+}

+ 12 - 0
src/main/java/com/example/springboot/entity/User/AccountUser.java

@@ -0,0 +1,12 @@
+package com.example.springboot.entity.User;
+
+import lombok.Data;
+
+@Data
+public class AccountUser {
+
+    int id;
+    String username;
+    String email;
+
+}

+ 31 - 0
src/main/java/com/example/springboot/interceptor/AuthorizeInterceptor.java

@@ -0,0 +1,31 @@
+package com.example.springboot.interceptor;
+
+import com.example.springboot.entity.User.AccountUser;
+import com.example.springboot.mapper.UserMapper;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+@Component
+public class AuthorizeInterceptor implements HandlerInterceptor {
+    @Resource
+    UserMapper userMapper;
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        SecurityContext context = SecurityContextHolder.getContext();
+        Authentication authentication = context.getAuthentication();
+        User user = (User) authentication.getPrincipal();
+        String username = user.getUsername();
+        AccountUser account = userMapper.findAccountUserByNameOrEmail(username);
+        request.getSession().setAttribute("account", account);
+        return true;
+    }
+}

+ 17 - 7
src/main/java/com/example/springboot/mapper/UserMapper.java

@@ -1,20 +1,30 @@
 package com.example.springboot.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.example.springboot.entity.User;
-import org.apache.ibatis.annotations.Delete;
+import com.example.springboot.entity.Auth.Account;
+import com.example.springboot.entity.Auth.User;
+import com.example.springboot.entity.User.AccountUser;
 import org.apache.ibatis.annotations.Insert;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Select;
-import org.springframework.context.annotation.Bean;
-import org.springframework.stereotype.Repository;
+import org.apache.ibatis.annotations.Update;
 
-import java.util.List;
-
-//@Mapper
+@Mapper
 //@Repository
 public interface UserMapper extends BaseMapper<User> {
 
+    @Select("select * from authorize where username = #{text} or email = #{text}")
+    AccountUser findAccountUserByNameOrEmail(String text);
+
+    @Select("select * from authorize where username = #{text} or email = #{text}")
+    Account findAccountByNameOrEmail(String text);
+
+    @Insert("insert into authorize(username, email, password) value (#{username}, #{email}, #{password})")
+    int createAccount(String username, String password, String email);
+
+    @Update("update authorize set password = #{password} where email = #{email}")
+    int resetPassword(String password, String email);
+
     /*@Select("select * from user")
     List<User> queryUserList();
 

+ 10 - 0
src/main/java/com/example/springboot/service/AuthorizeService.java

@@ -0,0 +1,10 @@
+package com.example.springboot.service;
+
+import org.springframework.security.core.userdetails.UserDetailsService;
+
+public interface AuthorizeService extends UserDetailsService {
+    String sendValidateEmail(String email, String sessionsId, boolean hasAccount);
+    String vaildateAndRegister(String username, String password, String email, String code, String sessionId);
+    String vaildateOnly(String email, String code, String sessionId);
+    boolean resetPassword(String password, String email);
+}

+ 1 - 1
src/main/java/com/example/springboot/service/IUserService.java

@@ -1,6 +1,6 @@
 package com.example.springboot.service;
 
-import com.example.springboot.entity.User;
+import com.example.springboot.entity.Auth.User;
 import com.baomidou.mybatisplus.extension.service.IService;
 
 /**

+ 1 - 2
src/main/java/com/example/springboot/service/UserService.java

@@ -1,9 +1,8 @@
 package com.example.springboot.service;
 
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.example.springboot.entity.User;
+import com.example.springboot.entity.Auth.User;
 import com.example.springboot.mapper.UserMapper;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 @Service

+ 149 - 0
src/main/java/com/example/springboot/service/impl/AuthorizeServiceImpl.java

@@ -0,0 +1,149 @@
+package com.example.springboot.service.impl;
+
+import com.example.springboot.entity.Auth.Account;
+import com.example.springboot.mapper.UserMapper;
+import com.example.springboot.service.AuthorizeService;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.mail.MailException;
+import org.springframework.mail.MailSender;
+import org.springframework.mail.SimpleMailMessage;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Optional;
+import java.util.Random;
+import java.util.concurrent.TimeUnit;
+
+@Service
+public class AuthorizeServiceImpl implements AuthorizeService {
+    @Value("${spring.mail.username}")
+    String from;
+
+    @Resource
+    UserMapper userMapper;
+
+    @Resource
+    MailSender mailSender;
+
+    @Resource
+    StringRedisTemplate template;
+
+    BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
+
+    @Override
+    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+        if (username == null){
+            throw new UsernameNotFoundException("用户名不能为空");
+        }
+        Account accountByNameOrEmail = userMapper.findAccountByNameOrEmail(username);
+        if (accountByNameOrEmail == null){
+            throw new UsernameNotFoundException("用户名或密码错误");
+        }
+        return User
+                .withUsername(accountByNameOrEmail.getUsername())
+                .password(accountByNameOrEmail.getPassword())
+                .roles("user")
+                .build();
+    }
+
+    /*
+     * 1、先生成对应的验证码
+     * 2、把邮箱和对应的验证码直接存放到Redis里(验证码过期时间为3分钟,如果想要重新发送验证码,需判断验证码剩余时间小于2分钟,才可重新发送)
+     * 3、发送验证码到指定邮箱
+     * 4、如果发送失败,需把Redis里刚刚插入的数据删除
+     * 5、用户在注册时,再从Redis中取出对应的键值对,然后判断验证码是否一致
+     * */
+    @Override
+    public String sendValidateEmail(String email, String sessionId, boolean hasAccount) {
+        String key = "email:" + sessionId + ":" + email + ":" + hasAccount;
+        System.out.println("key:" + key);
+        if (Boolean.TRUE.equals(template.hasKey(key))){
+            Long expire = Optional.ofNullable(template.getExpire(key, TimeUnit.SECONDS)).orElse(0L);
+            if (expire > 120){
+                return "请求频繁,请稍后再试";
+            }
+        }
+        Account dbUser = userMapper.findAccountByNameOrEmail(email);
+        if (hasAccount && dbUser == null){
+            return "没有此邮件地址的账户";
+        }
+        if (!hasAccount && dbUser != null){
+            return "此邮箱已注册用户,请更换其它邮箱";
+        }
+        Random random = new Random();
+        int code = random.nextInt(899999) + 100000;
+        SimpleMailMessage message = new SimpleMailMessage();
+        message.setFrom(from);
+        message.setTo(email);
+        message.setSubject("这是您注册程序所需的验证码邮件");//邮件标题
+        message.setText("验证码为:"+code);
+        System.out.println("验证码为:"+code);
+        try {
+            mailSender.send(message);
+            template.opsForValue().set(key,String.valueOf(code), 3, TimeUnit.MINUTES);
+            return null;
+        } catch (MailException e) {
+            e.getMessage();
+            return "邮件发送失败,请检查邮箱地址是否正确";
+        }
+    }
+
+    @Override
+    public String vaildateAndRegister(String username, String password, String email, String code, String sessionId) {
+        String key = "email:" + sessionId + ":" + email + ":false";
+        if (Boolean.TRUE.equals(template.hasKey(key))) {
+            String s = template.opsForValue().get(key);
+            if (s == null){
+                return "验证码失效,请重新获取";
+            }
+            if (s.equals(code)){
+                Account dbUser = userMapper.findAccountByNameOrEmail(username);
+                if (dbUser != null){
+                    return "用户名已被占用,请更换其它用户名!";
+                }
+                template.delete(key);
+                password = encoder.encode(password);
+                if (userMapper.createAccount(username, password, email) > 0){
+                    return null;
+                } else {
+                    return "内部错误,请联系管理员";
+                }
+            } else {
+                return "验证码错误,请核实后再提交";
+            }
+        } else {
+            return "请先获取验证码";
+        }
+
+    }
+
+    @Override
+    public String vaildateOnly(String email, String code, String sessionId) {
+        String key = "email:" + sessionId + ":" + email + ":true";
+        if (Boolean.TRUE.equals(template.hasKey(key))) {
+            String s = template.opsForValue().get(key);
+            if (s == null){
+                return "验证码失效,请重新获取";
+            }
+            if (s.equals(code)){
+                template.delete(key);
+                return null;
+            } else {
+                return "验证码错误,请核实后再提交";
+            }
+        } else {
+            return "请先获取验证码";
+        }
+    }
+
+    @Override
+    public boolean resetPassword(String password, String email) {
+        password = encoder.encode(password);
+        return userMapper.resetPassword(password,email) > 0;
+    }
+}

+ 1 - 1
src/main/java/com/example/springboot/service/impl/UserServiceImpl.java

@@ -1,6 +1,6 @@
 package com.example.springboot.service.impl;
 
-import com.example.springboot.entity.User;
+import com.example.springboot.entity.Auth.User;
 import com.example.springboot.mapper.UserMapper;
 import com.example.springboot.service.IUserService;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

+ 8 - 0
src/main/resources/META-INF/additional-spring-configuration-metadata.json

@@ -0,0 +1,8 @@
+{
+  "properties": [
+    {
+      "name": "spring.mail.host.username",
+      "type": "java.lang.String",
+      "description": "Description for spring.mail.host.username."
+  }
+] }

+ 0 - 4
src/main/resources/application.properties

@@ -1,4 +0,0 @@
-spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
-spring.datasource.url=jdbc:mysql://localhost:3306/boot?serverTimezone=GMT%2b8
-spring.datasource.username=root
-spring.datasource.password=root1120

+ 11 - 0
src/main/resources/application.yml

@@ -12,6 +12,17 @@ spring:
       exclude: WEB-INF/**
   freemarker:
     cache: false #页面不加载缓存,修改即时生效
+  mail:
+    host: smtp.163.com
+    username: li11207555@163.com
+    password: IEARUTBPSQTZULIX
+    port: 465
+    properties:
+      from: li11207555@163.com
+      mail:
+        smtp:
+          socketFactory:
+            class: javax.net.ssl.SSLSocketFactory
 server:
   port: 9090
 mybatis: