package com.zheng.upms.server.controller; import com.zheng.common.base.BaseController; import com.zheng.common.util.RedisUtil; import com.zheng.upms.client.shiro.session.UpmsSession; import com.zheng.upms.client.shiro.session.UpmsSessionDao; import com.zheng.upms.common.constant.UpmsResult; import com.zheng.upms.common.constant.UpmsResultConstant; import com.zheng.upms.dao.model.UpmsSystemExample; import com.zheng.upms.rpc.api.UpmsSystemService; import com.zheng.upms.rpc.api.UpmsUserService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.LockedAccountException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.net.URLEncoder; import java.util.UUID; /** * 单点登录管理 * Created by shuzheng on 2016/12/10. */ @Controller @RequestMapping("/sso") @Api(value = "单点登录管理", description = "单点登录管理") public class SSOController extends BaseController { private final static Logger _log = LoggerFactory.getLogger(SSOController.class); // 全局会话key private final static String ZHENG_UPMS_SERVER_SESSION_ID = "zheng-upms-server-session-id"; // 全局会话key列表 private final static String ZHENG_UPMS_SERVER_SESSION_IDS = "zheng-upms-server-session-ids"; // code key private final static String ZHENG_UPMS_SERVER_CODE = "zheng-upms-server-code"; @Autowired UpmsSystemService upmsSystemService; @Autowired UpmsUserService upmsUserService; @Autowired UpmsSessionDao upmsSessionDao; @ApiOperation(value = "认证中心首页") @RequestMapping(value = "/index", method = RequestMethod.GET) public String index(HttpServletRequest request) throws Exception { String appid = request.getParameter("appid"); String backurl = request.getParameter("backurl"); if (StringUtils.isBlank(appid)) { throw new RuntimeException("无效访问!"); } // 判断请求认证系统是否注册 UpmsSystemExample upmsSystemExample = new UpmsSystemExample(); upmsSystemExample.createCriteria() .andNameEqualTo(appid); int count = upmsSystemService.countByExample(upmsSystemExample); if (0 == count) { throw new RuntimeException(String.format("未注册的系统:%s", appid)); } return "redirect:/sso/login?backurl=" + URLEncoder.encode(backurl, "utf-8"); } @ApiOperation(value = "登录") @RequestMapping(value = "/login", method = RequestMethod.GET) public String login(HttpServletRequest request) { Subject subject = SecurityUtils.getSubject(); Session session = subject.getSession(); String serverSessionId = session.getId().toString(); // 判断是否已登录,如果已登录,则回跳 String code = RedisUtil.get(ZHENG_UPMS_SERVER_SESSION_ID + "_" + serverSessionId); // code校验值 if (StringUtils.isNotBlank(code)) { // 回跳 String backurl = request.getParameter("backurl"); String username = (String) subject.getPrincipal(); if (StringUtils.isBlank(backurl)) { backurl = "/"; } else { if (backurl.contains("?")) { backurl += "&upms_code=" + code + "&upms_username=" + username; } else { backurl += "?upms_code=" + code + "&upms_username=" + username; } } _log.debug("认证中心帐号通过,带code回跳:{}", backurl); return "redirect:" + backurl; } return "/sso/login.jsp"; } @ApiOperation(value = "登录") @RequestMapping(value = "/login", method = RequestMethod.POST) @ResponseBody public Object login(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) { String username = request.getParameter("username"); String password = request.getParameter("password"); String rememberMe = request.getParameter("rememberMe"); if (StringUtils.isBlank(username)) { return new UpmsResult(UpmsResultConstant.EMPTY_USERNAME, "帐号不能为空!"); } if (StringUtils.isBlank(password)) { return new UpmsResult(UpmsResultConstant.EMPTY_PASSWORD, "密码不能为空!"); } Subject subject = SecurityUtils.getSubject(); Session session = subject.getSession(); String sessionId = session.getId().toString(); // 判断是否已登录,如果已登录,则回跳,防止重复登录 String hasCode = RedisUtil.get(ZHENG_UPMS_SERVER_SESSION_ID + "_" + sessionId); // code校验值 if (StringUtils.isBlank(hasCode)) { // 使用shiro认证 UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password); try { if (BooleanUtils.toBoolean(rememberMe)) { usernamePasswordToken.setRememberMe(true); } else { usernamePasswordToken.setRememberMe(false); } subject.login(usernamePasswordToken); } catch (UnknownAccountException e) { return new UpmsResult(UpmsResultConstant.INVALID_USERNAME, "帐号不存在!"); } catch (IncorrectCredentialsException e) { return new UpmsResult(UpmsResultConstant.INVALID_PASSWORD, "密码错误!"); } catch (LockedAccountException e) { return new UpmsResult(UpmsResultConstant.INVALID_ACCOUNT, "帐号已锁定!"); } // 更新session状态 upmsSessionDao.updateStatus(sessionId, UpmsSession.OnlineStatus.on_line); // 全局会话sessionId列表,供会话管理 RedisUtil.lpush(ZHENG_UPMS_SERVER_SESSION_IDS, sessionId.toString()); // 默认验证帐号密码正确,创建code String code = UUID.randomUUID().toString(); // 全局会话的code RedisUtil.set(ZHENG_UPMS_SERVER_SESSION_ID + "_" + sessionId, code, (int) subject.getSession().getTimeout() / 1000); // code校验值 RedisUtil.set(ZHENG_UPMS_SERVER_CODE + "_" + code, code, (int) subject.getSession().getTimeout() / 1000); } // 回跳登录前地址 String backurl = request.getParameter("backurl"); if (StringUtils.isBlank(backurl)) { return new UpmsResult(UpmsResultConstant.SUCCESS, "/"); } else { return new UpmsResult(UpmsResultConstant.SUCCESS, backurl); } } @ApiOperation(value = "校验code") @RequestMapping(value = "/code", method = RequestMethod.POST) @ResponseBody public Object code(HttpServletRequest request) { String codeParam = request.getParameter("code"); String code = RedisUtil.get(ZHENG_UPMS_SERVER_CODE + "_" + codeParam); if (StringUtils.isBlank(codeParam) || !codeParam.equals(code)) { new UpmsResult(UpmsResultConstant.FAILED, "无效code"); } return new UpmsResult(UpmsResultConstant.SUCCESS, code); } @ApiOperation(value = "退出登录") @RequestMapping(value = "/logout", method = RequestMethod.GET) public String logout(HttpServletRequest request) { // shiro退出登录 SecurityUtils.getSubject().logout(); // 跳回原地址 String redirectUrl = request.getHeader("Referer"); if (null == redirectUrl) { redirectUrl = "/"; } return "redirect:" + redirectUrl; } }