Servlet的session授权方式
<html>
<body>
<h2>Hello Welcome!</h2>
</body>
<form action="/security/index" method="get">
Username: <input type="text" name="user"><br>
Password: <input type="password" name="password"><br>
<button type="submit">submit</button>
<%= request.getAttribute("message")%>
</form>
</html>
@WebServlet("/login")
public class RedirectController extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//转发
req.getRequestDispatcher("index.jsp").forward(req,resp);
//重定向
//resp.sendRedirect("/servlet2");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
@WebServlet("/index")
public class IdefyController extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("user");
String password = req.getParameter("password");
if (name.equals("xiaoxu") && password.equals("xiaoxu")){
resp.getWriter().write("login successful!");
}else {
req.setAttribute("message","user or pass incorrect");
req.getRequestDispatcher("index.jsp").forward(req,resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
表单模拟的验证登录面临的新问题是这个验证登录只对index资源有效,不走验证流程,查看其他资源也可以访问,这显然是不对的。那么如何实现权限的控制呢?
会话技术session
- 创建会话
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("user");
String password = req.getParameter("password");
if (name.equals("xiaoxu") && password.equals("xiaoxu")){
//session会话
HttpSession session = req.getSession();
session.setAttribute("isLogin","true");
PrintWriter writer = resp.getWriter();
writer.write("login successful!");
writer.write("<a href=\"/exit\"></a>");
}else {
req.setAttribute("message","user or pass incorrect");
req.getRequestDispatcher("index.jsp").forward(req,resp);
}
}
//session会话
HttpSession session = req.getSession();
session.setAttribute("isLogin","true");
通过请求参数在HtppSession对象的实例中添加参数,该对象的实例是全局的,服务器状态的会话技术,通过添加表示来记录登录的状态。
- 使用会话
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if(req.getSession().getAttribute("isLogin") == null){
resp.getWriter().write("Not currently logged in!");
}else {
if (req.getSession().getAttribute("isLogin").equals("true")){
req.setCharacterEncoding("utf-8");
PrintWriter out=resp.getWriter();
out.write("Test");
}else {
resp.getWriter().write("Not currently logged in!");
}
}
req.getSession().getAttribute("isLogin")
方法获取创建会话是存入会话的表示,确认登录状态。
当前并未登录
直接访问资源
登录成功后
直接在url上访问资源
如上所示可以实现权限的管理,但缺点是每个资源都需要对session的判断,比较繁琐:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
if(req.getSession().getAttribute("isLogin") == null){
resp.getWriter().write("Not currently logged in!");
}else {
if (req.getSession().getAttribute("isLogin").equals("true")){
req.setCharacterEncoding("utf-8");
PrintWriter out=resp.getWriter();
out.write("Test");
}else {
resp.getWriter().write("Not currently logged in!");
}
}
}
- 消除会话
消除用户鉴权的核心就是销毁会话存储的标识:
//消除session会话
HttpSession session = request.getSession();
session.removeAttribute("isLogin");
Filter的授权方式
更多内容请移步Java开发网站的核心servlet
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//super.init(filterConfig);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//请求和响应参数强转
HttpServletRequest res = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
if(res.getSession().getAttribute("isLogin") == null){
resp.getWriter().write("Not currently logged in!");
}else {
if (res.getSession().getAttribute("isLogin").equals("true")){
filterChain.doFilter(servletRequest,servletResponse);
}else {
resp.getWriter().write("Not currently logged in!");
}
}
}
@Override
public void destroy() {
//super.destroy();
}
}
这里将ServletRequest
强转为HttpServletRequest
//请求和响应参数强转
HttpServletRequest res = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
ServletRequest
只是一个接口,实现了HttpServletRequest
大多数方法,可以直接强转。
在web.xml配置fileter,也可以通过@WebFilter
注解:
<filter>
<filter-name>webFilter</filter-name>
<filter-class>com.example.controller.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>webFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
web.xml的配置是由加载顺序的,因此注意配置的顺序,利用顺序配置过滤器链,过滤器配置在servlet之前。
/*
表示所有路径。Filter的执行顺序与在web.xml配置文件中的配置顺序一致,一般把Filter配置在所有的Servlet之前。
配置后再启动服务器直接将主页也权限控制了:
这里的解决方案是放开登录的主页即利用filter排除过滤不需要的页面:
<!--web.xml中过滤全部-->
<filter>
<filter-name>webFilter</filter-name>
<filter-class>com.example.controller.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>webFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
过滤器中捕获相应需要释放的url:
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//请求和响应参数强转
HttpServletRequest res = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
if (res.getServletPath().equals("/login") || res.getServletPath().equals("/index")){
filterChain.doFilter(servletRequest,servletResponse);
}else {
if (res.getSession().getAttribute("isLogin") == null){
resp.getWriter().write("Not currently logged in!");
}
if (res.getSession().getAttribute("isLogin").equals("true")){
filterChain.doFilter(servletRequest,servletResponse);
}
}
}
分别释放/login和/index的原因是前者是返回的登陆页面,后者是登陆权限判断的逻辑处理。(逻辑处理不释放,会导致登录不上系统)
通过HttpServletRequest
对象的实例的getServletPath()
方法获取请求的uri,对特定的url直接释放资源例如:/login。注意需要带/
。
对特定uri释放资源后,只有特定的uri会被放行其他都会被拦截:
这里需要注意的是释放url的逻辑,看下图Filter的处理逻辑,既可以每个filter实现对servlet的过滤,也可以通过url的配置实现对整个servlet的控制:
案例的的filter的uri配置的是/*
对所有的url拦截,需要释放登录和逻辑判断。Filter在拦截时,会对请求时拦截和请求后处理,这涉及到Filter的生命周期,只要释放了相应的uri其后的逻辑既可以正常执行,无论是页面还是处理逻辑。
Filter登录权限控制总结:
- 实现Filter类,并重新写方法
public class LoginFilter implements Filter {
//重写方法
}
- 用户身份登录逻辑
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//请求和响应参数强转
HttpServletRequest res = (HttpServletRequest) servletRequest;
HttpServletResponse resp = (HttpServletResponse) servletResponse;
//需要释放的资源
if (res.getServletPath().equals("/login") || res.getServletPath().equals("/index")){
filterChain.doFilter(servletRequest,servletResponse);
}else {
//状态判断
if (res.getSession().getAttribute("isLogin") == null){
resp.getWriter().write("Not currently logged in!");
}
if (res.getSession().getAttribute("isLogin").equals("true")){
filterChain.doFilter(servletRequest,servletResponse);
}
}
}
请求和响应参数必须要强转,因为ServletRequest只是一个接口,没有实现具体方法;对登录页面和逻辑的资源放行;非登录逻辑相关必须验证登录状态使用会话技术。
- 登录逻辑与会话技术
继承HttpServlet并实现相关方法,在方法体内编写验证和会话逻辑。
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String name = req.getParameter("user");
String password = req.getParameter("password");
if (name.equals("xiaoxu") && password.equals("xiaoxu")){
//session会话
HttpSession session = req.getSession();
session.setAttribute("isLogin","true");
PrintWriter writer = resp.getWriter();
writer.write("login successful!");
}else {
req.setAttribute("message","user or pass incorrect");
req.getRequestDispatcher("/login").forward(req,resp);
}
}
不论通过ajxa还是form表单,这里都是查数据库验证角色是否存在,存在就设置会话标识,不存在返回登录页面并返回错误信息。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/156169.html