先介绍HttpServletRequest 用户请求对象
1.用户请求对象包含:
请求行 请求头 请求体
// 获取请求的网址
System.out.println(request.getRequestURL());
// http://localhost:8080/sh-web-servlet02/demo08
System.out.println(request.getRequestURI());
// /sh-web-servlet02/demo08
// 获取请求的类型(用浏览器直接请求都是get请求)
System.out.println(request.getMethod());// GET
// 获取请求路径 (相对路径)
System.out.println(request.getContextPath());// /sh-web-servlet02
// 获取请求中携带的参数
// 参数是 提交表单时 表单的name属性
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username + "..." + password);
// 判断浏览器
// 可以通过请求头中的信息获取用户使用的浏览器
String header = request.getHeader("User-Agent");
System.out.println(header);
if (header.toLowerCase().contains("firefox")) {
System.out.println("用的是火狐");
}else if (header.toLowerCase().contains("chrome")) {
System.out.println("用的是谷歌");
}else {
System.out.println("其他浏览器");
}
}
请求转发 请求重定向 请求包含
2. jetty实现api接口并生成token和添加cookie
jetty时比较轻量级的开源的服务器容器,相对于tomcat来说更轻量。便于用户进行第二次开发。具体的功能多在hondler中实现。多用于嵌入式行业中。
private void startJettyServer() {
String webPort = System.getenv("PORT");
if (webPort == null || webPort.isEmpty()) {
webPort = System.getProperty("PORT");
}
if (webPort == null || webPort.isEmpty()) {
webPort = "8080";
}
server = new Server(Integer.valueOf(webPort));
WebAppContext root = new WebAppContext();
ServletHolder loginServletHolder = new ServletHolder(new LoginServlet());
root.addServlet(loginServletHolder, "/login/*");
}
实现LoginServlet类
package org.eclipse.leshan.standalone.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import org.eclipse.leshan.standalone.utils.JwtUtil;
import net.sf.json.JSONObject;
public class LoginServlet extends HttpServlet
{
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
UserBean userBean = new UserBean();
JSONObject repResult = new JSONObject();
String username = request.getParameter("username");
String password = request.getParameter("password");
String encodePwd = DigestUtils.md5Hex(password);
HttpSession session = request.getSession();
User user = userBean.getUserByUserName(username);
response.setContentType("application/json");
if(user != null && user.getPasswd().equals(encodePwd)){
session.setAttribute("username", username);
String token = JwtUtil.generateToken(username, 1000*60*60);
repResult.put("status", ResponseCode.CHANGED.toString());
repResult.put("token", token);
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().print(repResult);
return;
}else {
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
response.getWriter().format(ResponseError.genResponseError("username or password error")).flush();
return;
}
}
}
实现jwttoken工具类:
package org.eclipse.leshan.standalone.utils;
import com.auth0.jwt.internal.org.apache.commons.codec.binary.Base64;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.eclipse.leshan.standalone.servlet.CommonServlet;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
public class JwtUtil {
private static final String signingKey = "signingKey";
public static String generateToken( String subject, long timeToAlive) {
SecretKey key = generalKey();
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
JwtBuilder builder = Jwts.builder()
.setSubject(subject)
.setIssuedAt(now)
.signWith(SignatureAlgorithm.HS256, key);
if (timeToAlive > 0) {
Date exp = new Date(nowMillis + timeToAlive);
builder.setExpiration(exp);
}
return builder.compact();
}
public static String getSubject(HttpServletRequest req, String jwtTokenCookieName){
SecretKey key = generalKey();
String token = req.getHeader(CommonServlet.headerName);
if(token == null) return null;
return Jwts.parser().setSigningKey(key).parseClaimsJws(jwtTokenCookieName).getBody().getSubject();
}
static private SecretKey generalKey() {
byte[] encodedKey = Base64.decodeBase64(signingKey);
SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
return key;
}
}
3.实现一个commonSevlet的类,当api访问时先验证token的值如果token有效然后调用相应的do函数
public class CommonServlet extends HttpServlet
{
public static final String headerName = "Authorization";
private static final Logger LOG = LoggerFactory.getLogger(CommonServlet.class);
private boolean isValid(HttpServletRequest httpServletRequest, String token){
try{
String uname;
HttpSession session = httpServletRequest.getSession();
String username = JwtUtil.getSubject(httpServletRequest, token);
uname = (String)session.getAttribute("username");
if(username == null || !uname.equals(username)){
return false;
}
}catch(Exception e){
LOG.info("jwtError:"+ e);
return false;
}
return true;
}
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String token = req.getHeader(headerName);
resp.setHeader("Access-Control-Allow-Origin", "*");
if(isValid(req, token)){
super.service(req, resp);
}else{
JSONObject repResult = new JSONObject();
JSONObject repObj = new JSONObject();
repResult.put("status", "error");
repResult.put("content", "illegal user");
repObj.put("result", repResult);
resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
PrintWriter toClient = resp.getWriter();
toClient.println(repObj);
}
}
}
4.cookie(客户端技术)
cookie是保存在浏览器中的缓存数据
当发起一个请求 请求一个servlet
进行逻辑处理(添加一个商品进购物车)
处理完成后 给客户端(浏览器)一个响应
响应中携带着记录了购买的什么商品的 cookie
让浏览器保存起来 可以是保存在内存当中(结束会话 cookie被清除)
也可以保存在硬盘当中(结束会话 依然存在 就是个文件)
当浏览器再一次请求购物车的时候
会携带着之前保存的 cookie 去访问
每个网站可以保存20个cookie 整个浏览器可以保存300个
注意:第一次访问服务器的时候 是不会携带着cookie去访问的
因为cookie还没有产生 只有当第一次请求后的响应中可以把cookie写回到浏览器中 利用cookie 显示上次登录的时间
package leshan.standalone.utils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CookieUtil {
public static void create(HttpServletResponse httpServletResponse, String name, String value, Boolean secure, Integer maxAge, String domain) {
Cookie cookie = new Cookie(name, value);
cookie.setSecure(secure);
cookie.setHttpOnly(true);
cookie.setMaxAge(maxAge);
cookie.setDomain(domain);
cookie.setPath("/");
httpServletResponse.addCookie(cookie);
}
public static void clear(HttpServletResponse httpServletResponse, String name) {
Cookie cookie = new Cookie(name, null);
cookie.setPath("/");
cookie.setHttpOnly(true);
cookie.setMaxAge(0);
httpServletResponse.addCookie(cookie);
}
public static String getValue(HttpServletRequest httpServletRequest, String name) {
Cookie[] cookies = httpServletRequest.getCookies();
if (cookies != null) {
// 遍历数组
for (Cookie cookie : cookies) {
if (cookie.getName().equals(name)) {
// 取出cookie的值
String value = cookie.getValue();
// 字符串转long
return value;
}
}
}
return null;
}
}
这样就实现了一个当用户第一次登录时,后台生成token后设置到前台的cookie中,并设置过期时间。然后当用户通过api再次访问的时候就可以验证cookie中的token。保证用户信息的安全性。