问题:在一次面试中,面试官看了我的项目后提出了一个问题,我的项目中登陆人员的角色有两种,一个是学生一个是老师,他说如果我知道了老师登陆表单所提交到的地址,那么我直接在URL中输入这个地址然后在后面按照GET方式请求那样加上我们自己的账号和密码(学生用户),那我们是不是能进入到老师的页面了,在业务中老师和学生的页面肯定是不同的,这种方式就实现了由学生账号进入到了老师的页面。当时他说的也没有这么清楚,平时我也没有这样想过,然后我就回顾我自己做的项目。写这篇文章只是模拟他说的那种操作
先来演示一个例子(使用表单post提交登陆和URL登陆)
前端登陆表单 post方式提交
<form action="studentLogin" method="post">
账号:
<input type="text" id="" name="account" /><br />
密码:
<input type="password" name="password" /><br />
<input type="submit" class="btn btn-danger" value="登呀!!">
</form>
后台验证
@RequestMapping(value="studentLogin")
public String studentLogin(HttpServletRequest request){
String account=request.getParameter("account");
String password=request.getParameter("password");
//模拟一个用户 账号为123 密码123456
if (account.equals("123")&&password.equals("123456")) {
return "student";
}
else {
System.out.println("true");
return "error";
}
}
使用前端页面表单登陆 前端页面如下
点击登陆后得到下面的结果
URL中的studentLogin为表单提交的地址,因为登陆后学生页面是由转发进入的,所以URL地址看到的是表单提交的地址,通过上述的表单代码也可以看到action="studentLogin"
现在我们知道表单提交地址即:http://localhost:8080/studentLogin
现在随便打开一个页面,通过这个URL按照GET携带参数的规则进行登陆 如下
回车打开
结果进入到了学生的页面,这种方式同样可以登陆,属于get请求
这个大家应该都能看明白
再来对他说的骚操作进行模拟
我们进行这样的设计,学生和老师分别使用自己独立的登录页,后台两个方法分别进行验证然后转发到相应的页面
前端两个不同的页面,登陆账号和密码都放在同一张表中
学生登陆:http://localhost:8080/stuLoginPage.html
教师登陆:http://localhost:8080/adLoginPage.html
//教师登陆页
<form action="adminLogin" method="post">
账号:
<input type="text" id="" name="account" /><br />
密码:
<input type="password" name="password" /><br />
<input type="submit" class="btn btn-danger" value="登呀!!">
</form>
//学生登陆页
<form action="studentLogin" method="post">
账号:
<input type="text" id="" name="account" /><br />
密码:
<input type="password" name="password" /><br />
<input type="submit" class="btn btn-danger" value="登登登!!">
</form>
后端控制层代码
//处理学生登陆
@RequestMapping(value="studentLogin")
public String studentLogin(HttpServletRequest request){
String account=request.getParameter("account");
String password=request.getParameter("password");
if (account.equals("123")&&password.equals("123456")) {
return "student";
}
else {
System.out.println("true");
return "error";
}
}
//处理教师登陆
@RequestMapping(value="adminLogin")
public String adminLogin(HttpServletRequest request){
String account=request.getParameter("account");
String password=request.getParameter("password");
//通过账号和密码去数据库查询用户
Account account2=logService.getOne(account, password);
System.out.println(account2);
//用户存在则转发到教师页
if (account2!=null) {
return "teacher";
}
else {
System.out.println("true");
return "error";
}
上述控制层代码中,只通过账号和密码去查询用户,假设我们知道老师的登陆请求提交地址,从代码中可以看出地址应该是:http://localhost:8080/adminLogin 在第一个例子中可以知道这个请求提交地址在管理员登陆成功后在URL中就能看到,虽然我们没有账号不能通过登陆来得到这个地址,但是毕竟是个显式地东西,很容易得知。我们打开教师页面,用Google chrome开发者工具
现在我们拿到了这个地址 用第一个示例URL登陆来骚操作一波
账号123密码123456是数据库中真实存在的一个用户 假设这是一个学生 结果如下
是不是用学生进入到了这个页面 我们就能进入这个页面来更改我们的成绩了,挂科的改成90
你就做梦吧!
我们来看看控制层的注解
@RequestMapping(value="studentLogin")
这里我们没有显式指定该方法处理什么类型的请求,默认处理所有请求。在这里表单提交登陆是post方式,我们在URL中的骚操作是GET方式,所以都能进行处理
现在我们在注解中指定处理参数 @RequestMapping(value="adminLogin",method=RequestMethod.POST)再进行操作
注解中指定了只接收处理post方式,所以在URL携带参数便不能实现了
在我自己项目中,登陆模块我是这样设计的
数据库:学生和老师的账号信息都刚在同一张表中,表中字段除了账号和密码还有一个字段role用于保存用户的身份信息,role=0表示身份为老师,role=1表示身份是学生
前端:只有一个页面,学生和老师都在这个页面进行登陆,所以表单请求的地址也都只有一个,表单中也没有提供单选按钮进行身份选择,只需输入账号和密码进行登陆
后台:一个处理方法,接收前端传输过来的账号和密码,然后通过账号和密码去数据库查询用户,将查询到的信息用一个Account对象保存,然后对该对象进行判断,如果为null即不存在则重定向到登陆页,如果存在,则继续判断,此时判断该对象的role属性的值,如果为0就转发到教师页面,为1就转发到学生页面。我觉得在自己的项目中不会存在他说的问题,即便没有指定只处理post请求,或者说存在问题但是自己还没发现
下面是我的后台验证代码
@RequestMapping(value="adminLogin") public String adminLogin(HttpServletRequest request){ String account=request.getParameter("account"); String password=request.getParameter("password"); Account account1=logService.getOne(account, password); if (account1!=null) { if (account1.getRole()=0) { return "teacher"; } else return "student"; } else { return "redirect:loginPage.html"; }
他说的那个问题我们在刚才也模拟了,的确可以达到。但是在平时的项目设计中,有多大的几率出现这样的问题?
这个例子可以当个知识点进行一个了解,他说的那种方式属于get请求,如果我们只想通过登录页的表单来进行登陆请求,那在后台指定控制层方法的处理方式,屏蔽掉对get方式请求的处理。
作为还没入门的菜鸟,欢迎大家吐槽、