SpringBoot+vue 前后端的分离项目笔记 [二] 用户登录验证

用户登录验证主要涉及Token+Jpa+BCryptPasswordEncoder密码验证。

SpringBoot方面

@Entity(name ="manager")
@Data
public class User extends AbstractEntity {


    String username;

    String password;

    String email;

}
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class AbstractEntity {

    @Id
    @GeneratedValue
    @Getter
    @Setter
    Long id;

    @CreatedDate
    LocalDateTime createdDate;
    @LastModifiedDate
    LocalDateTime modifiedDate;
}

创建对应实体类的Jpa操作接口

public interface UserRespority extends Repository<User,Long> {

    Optional<User> findById(Long id);
    Optional<User> findByUsername(String username);
}

tokan方面参考连接:vue+springboot前后端分离实现token登录验证和状态保存的简单实现方案
修改Token工具包,方便后面提取token中的用户信息

TokenUtil.java

  /**
     * 签名验证
     * @param token
     * @return
     */
    public static User verify(String token){
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build();
            DecodedJWT jwt = verifier.verify(token);
            User user = new User();
            user.setId(jwt.getClaim("useid").asLong());
            user.setUsername(jwt.getClaim("username").asString());
            return user;
        } catch (Exception e){
            return null;
        }
    }

修改tokan拦截器,提取token中的用户信息到request

TokenInterceptor.java

......
 response.setCharacterEncoding("utf-8");
 String token = request.getHeader("Authorization");

  if(token != null){
      User result = TokenUtil.verify(token);
          if(result != null){
               request.setAttribute("user",result);
               return true;
         }
    }
......

整合过滤请求,跨域,以及后面用到的密码验证的安全配置
具体配置教程参考

/**
 * 安全配置类
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {
    private TokenInterceptor tokenInterceptor;
    //构造方法
    public WebSecurityConfig(TokenInterceptor token){
        this.tokenInterceptor = token;
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowCredentials(true)
                .allowedHeaders("*")
                .allowedMethods("*")
                .allowedOrigins("*");
    }

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer){
        configurer.setTaskExecutor(new ConcurrentTaskExecutor(Executors.newFixedThreadPool(3)));
        configurer.setDefaultTimeout(30000);
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry){
        List<String> excludePath = new ArrayList<>();
        //排除拦截,除了注册登录(此时还没token),其他都拦截
        excludePath.add("/user/register");  //注册
        excludePath.add("/user/getImgCode");  //获取验证码
        excludePath.add("/user/login");     //登录
        excludePath.add("/static/**");  //静态资源
        excludePath.add("/assets/**");  //静态资源

        registry.addInterceptor(tokenInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns(excludePath);
        WebMvcConfigurer.super.addInterceptors(registry);
    }
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", buildConfig());
        return new CorsFilter(source);
    }

    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        // 1允许任何域名使用
        corsConfiguration.addAllowedOrigin("*");
        // 2允许任何头
        corsConfiguration.addAllowedHeader("*");
        // 3允许任何方法(post、get等)
        corsConfiguration.addAllowedMethod("*");
        return corsConfiguration;
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/**").permitAll()
                .anyRequest().authenticated()
                .and().csrf().disable();
    }
}

BCryptPasswordEncoder密码验证

使用BCryptPasswordEncoder主要是因为数据库的用户登录密码是另一个laravel项目中加密的,要在SpringBoot中验证登录的话,就需要用到BCryptPasswordEncoder。(如不需要,可略过)
具体配置,参考教程:Spring security中的BCryptPasswordEncoder方法对密码进行加密与密码匹配

修改控制器

增加登录验证以及token验证

@RestController
@SpringBootApplication
@RequestMapping("/user")
public class LoginControll {

    @Autowired
   private UserRespority userRespority;

    //生成验证码
    @RequestMapping(value = "/getImgCode")
    @ResponseBody
    public Map<String, String> getImgCode() {
        Map<String, String> result = new HashMap<>();
        try {
            result = ImgValidateCodeUtil.getImgCodeBaseCode(4);
        } catch (Exception e) {
            System.out.println(e);
        }
        return result;
    }
    @RequestMapping(value = "/login",method = RequestMethod.POST)
    @ResponseBody
    public String login(@RequestBody Map<String,Object> para) throws JsonProcessingException {
        HashMap<String,Object> hs=new HashMap<>();
        try {
            //获取用户信息
            User user = userRespority.findByUsername((String)para.get("username")).get();
            BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
//            System.out.println(user.getId());
            if(bCryptPasswordEncoder.matches((String)para.get("password"),user.getPassword())){
                String token= TokenUtil.sign(user);
                hs.put("code",200);
                hs.put("token",token);
            }else {
                hs.put("code",400);
                hs.put("msg","密码错误");
            }

        }catch (NoSuchElementException e){
            hs.put("code",400);
            hs.put("msg","用户名不存在");
            ObjectMapper objectMapper=new ObjectMapper();
        }
        ObjectMapper objectMapper=new ObjectMapper();
        return objectMapper.writeValueAsString(hs);
    }

    @RequestMapping(value = "/yztokan")
    @ResponseBody
    public Map<String, String> yztokan(@RequestAttribute(value = "user") User user){
        Map<String, String> result = new HashMap<>();
        result.put("user",user.getUsername());
        return  result;
    }

}

vue方面

token配置参考教程: vue+springboot前后端分离实现token登录验证和状态保存的简单实现方案

修改登录方法

 /*登录*/
            tologin:function () {
                // this.$axios.post('user/getImgCode')
                let v = this.loginForm;
             if (v.inputCode === this.code){

                 // this.$layer.alert("验证通过!");
                 this.$axios.post('user/login',{
                     'username':v.username,
                     'password':v.password
                 }).then((response) => {
                     // console.log(response)
                     if (response.data.code === 200){
                         this.userToken = response.data.token;
                         this.changeLogin({Authorization:this.userToken});
                         this.$layer.msg("登录成功!");
                         // console.log(this.userToken)
                         this.$router.push('/');
                     }else {
                         this.getIdentifyingCode();
                         this.$layer.alert(response.data.msg);
                     }

                 }).catch((error) => {
                     console.log(error)
                 });
             }else {
                 this.$layer.alert("验证错误");
             }
            }
        }

增加token验证方法

ceshi:function () {
       // console.log(localStorage.getItem('Authorization'))
       this.$axios.get('user/yztokan')
               .then((response) => {

                console.log(response)
               })
               .catch((error) => {
                console.log(error);
               });
      }

效果图

SpringBoot+vue 前后端的分离项目笔记 [二] 使用 Token+Jpa+BCryptPasswordEncoder密码验证

SpringBoot+vue 前后端的分离项目笔记 [二] 使用 Token+Jpa+BCryptPasswordEncoder密码验证

SpringBoot+vue 前后端的分离项目笔记 [二] 使用 Token+Jpa+BCryptPasswordEncoder密码验证

其他参考教程:
官方:Spring Data JPA
相关代码:github.com/spring-projects/spring-...
vue怎么修改title
vue项目中使用vue-layer弹框插件

本作品采用《CC 协议》,转载必须注明作者和本文链接
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!