java中shiro实现登录

今天给大家分享个java中shiro的登录代码

package com.zdb.controller;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.alibaba.fastjson.JSON;
import com.zdb.entity.BaseOauth;
import com.zdb.entity.BaseOauthRecord;
import com.zdb.entity.BaseUser;
import com.zdb.service.LoginService;
import com.zdb.service.OauthService;
import com.zdb.shiro.ShiroSecurityHelper;
import com.zdb.util.ApplicationUtil;
import com.zdb.util.JsonCodeEnum;
import com.zdb.util.JsonDataUtil;
import com.zdb.util.ResultUtil;

@Controller
@RequestMapping("/login")
public class LoginController {
	
	@Autowired
	private LoginService loginService; 
	@Autowired
	private OauthService oauthService;
	@Autowired
	private ShiroSecurityHelper shiroSecurityHelper;

	
	/****************************************  退出  ************************************************/
	
	@ResponseBody
	@RequestMapping(value="/retreat",produces = "application/json; charset=utf-8")
	public String retreat(HttpServletRequest request){
		String token = request.getHeader("token");
		
		BaseOauth record = new BaseOauth();
		record.setAccessToken(token);
		List<BaseOauth> list = oauthService.selectByCondition(record);
		if(list.size() >0){
			record = list.get(0);
			String sessionId = record.getSessionId();
			Session session = shiroSecurityHelper.getSessionById(sessionId);
			session.setAttribute("logout", "logout");
		}
		SecurityUtils.getSubject().logout();
		return new JsonDataUtil(JsonCodeEnum.EC_20000, "退出成功").toJson();
	}
	
	
	/******************************************  登录     ************************************************/
	@RequestMapping(value="/login",produces = "application/json; charset=utf-8") 
	@ResponseBody  
//	@CrossOrigin(origins = {"*"})
	public String backLogin(String loginName,String loginPwd,String client_id,String redirect_uri,HttpServletRequest request,HttpServletResponse response){
		if (StringUtils.isEmpty(loginName) || StringUtils.isEmpty(loginPwd) || StringUtils.isEmpty(client_id))
		{
			return JSON.toJSONString(new JsonDataUtil(JsonCodeEnum.EC_20003, "传递的参数信息不全"));
		}
		
		//客户端判断
		String judgePlatform = loginService.judgePlatform(client_id);     //根据id查找访问凭证
		//返回的字符串是否与比对的字符串error 匹配
		if(judgePlatform.startsWith("error")){   
			return ResultUtil.getReturnResult(judgePlatform);
		}
		
		//登录信息判断
		Object login = loginService.judgeLogin(loginName, loginPwd);	//根据逻辑层返回的的是对象还是字符串如果是字符串就是登陆失败
		if(login instanceof String){
			return ResultUtil.getReturnResult(login);
		}
		BaseUser user = (BaseUser)login;							//返回的是对象  把返回的对象强转成user对象。
		//获取这个已登录对象的UserId
		String userId = user.getUserId();							//获取这个已登录对象的UserId
		Subject subject = SecurityUtils.getSubject();			 //得到Subject
		
		//登录
		try {
			String key= userId +"_"+ client_id;						//根据userId和登录web端凭证
			AuthenticationToken token = new UsernamePasswordToken(key, "1"); //得到创建用户名/密码身份验证Token(即用户身份/凭证)  
			subject.login(token);									//登录,即身份验证  
		} catch (Exception e) {	
			e.printStackTrace();									//身份验证失败								
			return  new JsonDataUtil(JsonCodeEnum.EC_20004, "登录失败,异常").toJson();
		} 
		
		//保存登录信息 
		Session session = subject.getSession(); //可获取会话
		session.setAttribute("userId", userId);	//保存登录账号
		session.setAttribute("client_id", client_id); //保存登录客户端
		if("edcd4e6bad8a11e795f900219b160fec".equalsIgnoreCase(client_id)){
			session.setTimeout(1000*60*60*24*30);
		}
		
		//创建访问凭证
		String accessToken = createOauth(session, client_id, userId); //创建访问凭证
		
		if(StringUtils.isEmpty(redirect_uri)){
			return new JsonDataUtil(JsonCodeEnum.EC_20000, accessToken).toJson();
		}else{
			Map<String, String> queryParams = new HashMap<String, String>();
			queryParams.put("token", accessToken);					//返回一个token的accessToken
			try {
				WebUtils.issueRedirect(request, response, redirect_uri, queryParams );
			} catch (IOException e) { 
				e.printStackTrace();
			}
			return null;
		}
		
	}
	
	/**
	 * 清除旧的访问信息,插入新的访问信息,
	 * @param session
	 * @param client_id
	 * @param userId
	 * @return	返回访问凭证
	 */
	private String createOauth(Session session, String client_id, String userId) {
		
		//清除认证表中的凭证,客户端和账号,保存入历史表
		BaseOauth record = new BaseOauth();
		record.setAppId(client_id);
		record.setUserId(userId);
		List<BaseOauth> list = oauthService.selectByCondition(record);  //根据Id查找凭证
		Date recordTime = new Date();
		for (BaseOauth oauth : list) {
			
			String authId = oauth.getAuthId();
			String sessionId = oauth.getSessionId();
			
			oauthService.deleteOauthByPrimaryKey(authId);			//删除凭证数据库表中数据根据凭证Id
			//清除失效的session缓存
			shiroSecurityHelper.deleteBySessionId(sessionId);		//根据您sessionId删除redis失效的缓存
		}
		
		//清除权限缓存
		String key= userId +"_"+ client_id;							
		shiroSecurityHelper.deletePermissionCache(key);			//清除权限缓存
		
		//插入新的访问凭证 
		String authId = ApplicationUtil.randomUUID();			//创建id
		String accessToken = ApplicationUtil.randomUUID(); 		//随机生成accessToken
		String sessionId = (String) session.getId();
		BaseOauth oauth = new BaseOauth(authId, userId, client_id, accessToken, sessionId, recordTime);
		oauthService.insertOauth(oauth);						//存入凭证
		
		BaseOauthRecord baseOauthRecord = new BaseOauthRecord(ApplicationUtil.randomUUID(), authId, userId, client_id, accessToken, sessionId, recordTime, recordTime);
		oauthService.insertOauthRecord(baseOauthRecord); 		//存入凭证记录表
		
		
		return accessToken;
	}

下面是他里面所封装的一些方法

	@Override
	public String judgePlatform(String clientId) {
		BasePlatform platform = new BasePlatform();
		platform.setIsDeleted(false);
		platform.setIsDisabled(false);
		platform.setAppId(clientId);
		List<BasePlatform> list = platformDao.selectByCondition(platform);
		if(list.size()<1){
			return ResultUtil.setErrorResult("登录客户端不能使用");
		}
		return ResultUtil.setSuccessResult("客户端可以使用");
	}

    @Override
	public Object judgeLogin(String loginName, String loginPwd) {
		//密码三次错误,出现验证码,10次错误今天不能登录
	
		// 已登陆则 跳到首页
		//10次是这个账号还是这个人被禁止登录
		//是一个客户端还是所有客户端
		//账号不存在
		BaseLogin login = new BaseLogin();
		login.setLoginName(loginName);
		List<BaseLogin> logins = loginDao.selectByCondition(login);  //查看账号是否存在
		if(logins.size() < 1){										 //存在查找数据大于1返回error
			return ResultUtil.setErrorResult("login-error1");	
		}			
		login = logins.get(0);										//账号存在而且没有重复账号  获取到返回 对象
	
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); //获取当前时间
		String format = sdf.format(new Date());					  //key为登录账号的loginId加当前登录时间
		String key = login.getLoginId() + format;
		String randomKey = login.getRandomKey();   //获得查出来的随机 盐
		//根据密码 随机盐去跟数据库密码比对
		if(!login.getLoginPwd().equals(PasswordUtil.encryptByPasswordAndSalt(loginPwd, randomKey))){  //经过解析查看密码是否匹配  密码不正正确走if逻辑
			//密码是否正确
			Long incr = redisService.incr(key);				//根据login自动自增(根据key值存入redis中)
			redisService.expire(key, 24*60*60);				//设置key生存时间为24*60*60秒
			if(incr>=10){									//如果自增的大于10等于10将禁止登录
				return ResultUtil.setErrorResult("login-error6");
			}else{
			return ResultUtil.setErrorResult("login-error2/"+incr);  //小于10时候给他提示密码错误还有还剩几次
			}
		}else  if(login.getIsLocked()){						//查看登录的账号是否锁定 锁定也也抛出异常
			//账号锁定
			return ResultUtil.setErrorResult("login-error4");
		}else if(login.getIsDeleted()){						//查看登录的账号是否删除 锁定也也抛出异常
			//是否删除
			return ResultUtil.setErrorResult("login-error5");
		}
		String value = redisService.get(key);				//获取redis中村的自增值如果大于10 或者取出的值不为空  直接报错。当账号密码匹配不会走向redis存值得代码
		if(value != null && Long.parseLong(value) >10){
			return ResultUtil.setErrorResult("login-error6");
		}
		
		redisService.del(key);								//清空redis寄存的值
		
		String userId = login.getUserId();					//获取userId
		BaseUser user = userDao.selectByPrimaryKey(userId);//根据userId查去user对象
		if(user == null){									//如果查出为空接着抛异常
			return ResultUtil.setErrorResult("login-error1");
		}else if(user.getIsDeleted()){						//如果USER中是否删除接着抛异常
			return ResultUtil.setErrorResult("login-error5");
		}
		
		return user;										//最后返回user对象
	}

我也不太懂 可能有点注释写的不太对 请大家多多指教。有错大家可以帮我指出来。谢谢

猜你喜欢

转载自blog.csdn.net/qq_38092788/article/details/81559450
今日推荐