测试开发系列之——用户登录、用户退出&个人中心功能

Mybatis-plus自动填充功能

Mybatis-plus有个自动填充的功能,可以对数据库进行更新和插入时间。
@Component 每个表都是一样的字段名
需要在MyMetaObjectHandler.java中添加注解:@Component
在这里插入图片描述

project项目表的外键是create_user,说明这个项目属于哪个用户的。需要显示项目信息,必须要知道用户信息。
data == userId
message == sessionId

后端对com.one.controller中
UserController.java进行修改

User loginUser = (User)subject.getPrincipal();
result = new Result("1", loginUser, sessionId);

前端修改login.html

$.cookie("sessionId", ret.message, {
								expires : date
							});

前端存储

  • 浏览器端存储数据的依据
    W3Cschool相关参考文档,两个对象:
    HTML5 提供了两种在客户端存储数据的新方法:
对象名 作用
localStorage 没有时间限制的数据存储
sessionStorage 针对一个session的数据存储,当用户关闭浏览器窗口后,数据会被删除
  • sessionStorage.setItem(‘userId’,ret.data);

前端login.html的代码修改

let userId = ret.data;
sessionStorage.setItem("userId", userId);

用户退出功能

后端代码:

	//退出功能
	@GetMapping("/logout")
	@ApiOperation(value="退出方法", httpMethod="GET")
	public Result logout(){
		Result result = null;
		//从shiro退出会话
		SecurityUtils.getSubject().logout();
		result = new Result("1","账号未登录");
		return result;
	}

前端代码:

<a href="javascript:logout()">退出</a>

    function logout(){
        //异步请求后端
        $.ajax({
            url:lemon.config.global.adminUrl + "/user/logout", 
            type:"GET",
            success:function(ret){
                if(ret.status==1&&ret.message=="账号未登录"){
                    location.href = lemon.config.global.rootUrl + "/html/login.html";
                }
            }
        });
    }

跨域问题

尝试退出功能,遇到跨域问题。为什么加了注解@CrossOrigin,还是会有跨域问题,因为会话管理被shiro拦截了,被shiro拦截后,要先比对sessionId。
不像之前都放行了,所以要先比对好这个。这个比对正确,是我们的安全用户,才让进入到它的后端控制层,也就是让进入到userlogout。
跨域问题截图:

解决方法:
在com.one.shiro下面新增CustomSessionManager.java文件。
CustomSessionManager继承了默认的DefaultWebSessionManager,指定了头的key叫Authorization,也就是前端传过来的头,就是它。不是特定的,就是要对上,这边写的是什么,前端就写成什么。
CustomSessionManager.java的代码如下:

package com.one.shiro;

import java.io.Serializable;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;

public class CustomSessionManager extends DefaultWebSessionManager {
	
	private static final String AUTHORIZATION ="Authorization";
	
	private static final String REFERENCED_SESSION_ID_SOURCE = "cookie";
	
	
	@Override
	protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
		
		String sessionId = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
		
		if (StringUtils.isNotEmpty(sessionId)) {
			request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sessionId);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
            return sessionId;
		}
		return super.getSessionId(request, response);
	}
}

前端projectList.html代码修改

ajax请求中加入headers:

    function logout(){
        let sessionId = $.cookie("sessionId");
        //异步请求后端
        $.ajax({
            headers:{"Authorization":sessionId},
            url: lemon.config.global.adminUrl + "/user/logout",
            type:"GET",
            success:function(ret){
                if(ret.status==1&&ret.message=="账号未登录"){
                    location.href = lemon.config.global.rootUrl + "/html/login.html";
                }
            }
        });
    }

StringUtils报错解决

其中StringUtils有报错,是因为是第三方,也是apache下面的一个工具jar包:lang3,经常用它来对字符串做一些常用的判断。
其中,非空判断是它其中用得最多的一个方法。

将下面这个jar包,要加进来。

		<dependency>
    		<groupId>org.apache.commons</groupId>
    		<artifactId>commons-lang3</artifactId>
    		<version>3.4</version>
		</dependency>

放开ShiroConfig.java中,对于SessionManager方法的注释:

	@Bean
	public SessionManager sessionManager(){
		CustomSessionManager manager = new CustomSessionManager();
	        manager.setSessionDAO(new EnterpriseCacheSessionDAO());
		return manager;
	}

在ShiroConfig.java中,告诉SecurityManager我现在换了session管理器,这就是set注入。

	@Bean
	public SecurityManager securityManager(MyRealm myReal) {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		 //自定义session管理
        securityManager.setSessionManager(sessionManager());
		// 设置realm
		securityManager.setRealm(myReal);
		return securityManager;
	}

遇到Uncaught TypeError: $.cookie is not a function这个错误,是需要引入jquery.cookie.js,加入到projectList.html文件中。

<script type="text/javascript" src="/lemon/js/jquery.cookie.js" charset="UTF-8"></script>

发现跨域问题还是未解决,请出终极法宝,让所有的控制器都支持跨域。
把UserControl.java中这边的@CrossOrigin注释掉,就不要去写这个了。
在这里插入图片描述
在com.one.handler包下面,加入CorsConfig.java跨域过滤器,跨域问题最终解决。
二者取其一,用了过滤器,就不要用CrossOrigin。
Bean把类对应的对象放到Spring容器当中,下面把这个对象new出来return new CorsFilter(source);
source注册了一个跨域的配置source.registerCorsConfiguration,/**表示对所有的控制层请求进行跨域处理,用buildConfig()方法处理。
CorsConfig.java的代码如下:

package com.one.handler;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CorsConfig {

	private CorsConfiguration buildConfig() {
		CorsConfiguration corsConfiguration = new CorsConfiguration();
		corsConfiguration.setAllowCredentials(true);
		corsConfiguration.addAllowedOrigin("*"); // 1
		
		corsConfiguration.addAllowedHeader("*"); // 2

		corsConfiguration.addAllowedMethod("*"); // 3
		return corsConfiguration;
	}

	@Bean
	public CorsFilter corsFilter() {

		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

		source.registerCorsConfiguration("/**", buildConfig()); // 4

		return new CorsFilter(source);
	}
}

遇到的问题汇总

问题一:登录成功的时候,忘记写result,导致用户登录成功,返回为空。status code是200,没有response data。而用户名错误和密码错误的情况都已经可以了,但是用正确的用户名和密码登录不能成功。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
问题二:用户登录报如下警告:
Thu Feb 20 19:49:19 CST 2020 WARN: Establishing SSL connection without server’s identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn’t set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to ‘false’. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.

解决方法:
在application.yml文件中,数据库url后加入useSSL=false,问题解决。
在这里插入图片描述
问题三:没有登录,就退出,会报用户未认证的错误。
在项目列表页面,如果进行页面刷新,再点击退出的话,会报用户未认证的错误,用户未登录,怎么可以登出呢?
用户只有登录后,才会有正确的sessionId,把正确的sessionId给了浏览器之后,浏览器异步提交带过来,才是真正对上暗号。
如果未登录,shiro没有正确的sessionId,这边随便的一个sessionId过去,那肯定是不对的。cookie存的是前一个的,不是当前的,所以肯定是unauth,没有验证上。

解决方法:
后端对com.one.controller中
UserController.java进行修改,加入未授权方法。

	//未授权方法
	@GetMapping("/unauth")
	@ApiOperation(value="未授权方法", httpMethod="GET")
	public Result unauth(){
		Result result = null;
		result = new Result("1","账号未登录");
		return result;
	}
发布了27 篇原创文章 · 获赞 1 · 访问量 1658

猜你喜欢

转载自blog.csdn.net/anniewhite/article/details/104436492