LoginController.java 13.1 KB
Newer Older
liqin's avatar
liqin committed
1 2 3 4 5
package cn.wisenergy.chnmuseum.party.web.controller;

import cn.wisenergy.chnmuseum.party.auth.SHA256PasswordEncryptionService;
import cn.wisenergy.chnmuseum.party.auth.util.JwtTokenUtil;
import cn.wisenergy.chnmuseum.party.common.checkcode.SpecCaptcha;
wzp's avatar
wzp committed
6 7
import cn.wisenergy.chnmuseum.party.common.enums.AuditOperationEnum;
import cn.wisenergy.chnmuseum.party.common.enums.AuditStatusEnum;
8 9 10
import cn.wisenergy.chnmuseum.party.common.log.MethodLog;
import cn.wisenergy.chnmuseum.party.common.log.OperModule;
import cn.wisenergy.chnmuseum.party.common.log.OperType;
wzp's avatar
wzp committed
11
import cn.wisenergy.chnmuseum.party.model.Audit;
12 13
import cn.wisenergy.chnmuseum.party.model.Role;
import cn.wisenergy.chnmuseum.party.model.TUser;
liqin's avatar
liqin committed
14
import cn.wisenergy.chnmuseum.party.model.Menu;
15 16
import cn.wisenergy.chnmuseum.party.service.RoleService;
import cn.wisenergy.chnmuseum.party.service.impl.TUserServiceImpl;
liqin's avatar
liqin committed
17
import cn.wisenergy.chnmuseum.party.service.impl.MenuServiceImpl;
wzp's avatar
wzp committed
18
import cn.wisenergy.chnmuseum.party.web.controller.base.BaseController;
liqin's avatar
liqin committed
19
import com.alibaba.fastjson.JSONObject;
liqin's avatar
liqin committed
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
import io.swagger.annotations.Api;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
wzp's avatar
wzp committed
39
import java.time.LocalDate;
40
import java.util.*;
liqin's avatar
liqin committed
41 42 43 44 45 46 47
import java.util.concurrent.TimeUnit;

/**
 * shiro权限控制登录Controller
 */
@Api(tags = "登录接口")
@RestController
wzp's avatar
wzp committed
48
public class LoginController extends BaseController {
liqin's avatar
liqin committed
49 50 51 52 53 54 55

    private static final Logger LOGGER = LoggerFactory.getLogger(LoginController.class);

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
56 57 58 59
    private TUserServiceImpl userService;

    @Resource
    private RoleService roleService;
liqin's avatar
liqin committed
60 61 62 63 64 65 66

    @Resource
    private MenuServiceImpl menuService;

    @Resource
    private SysLogController sysLogController;

liqin's avatar
liqin committed
67
    private static final String SHIRO_JWT_TOKEN = "shiro:jwt:token:";
liqin's avatar
liqin committed
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
    //用户登录次数计数  redisKey 前缀
    private String SHIRO_LOGIN_COUNT = "shiro_login_count_";
    //用户登录是否被锁定    一小时 redisKey 前缀
    private String SHIRO_IS_LOCK = "shiro_is_lock_";

    // 未授权跳转的页面
    @RequestMapping(value = "403", method = RequestMethod.GET)
    public void noPermissions(HttpServletResponse response) throws IOException {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=utf-8");
        response.setStatus(403);
        response.getWriter().write("{\"status\":403,\"message\":\"Unauthorized!\"}");
    }

    /**
     * 管理员ajax登录请求 后端用户登录
     *
     * @param username
     * @param password
     * @return
     */
    @RequestMapping(value = "ajaxLogin", method = RequestMethod.POST)
    public ResponseEntity<Map<String, Object>> ajaxLogin(@RequestParam(value = "username", required = true) String username,
                                                         @RequestParam(value = "password", required = true) String password,
92
//                                                         @RequestParam(value = "captcha", required = true) String captcha,
liqin's avatar
liqin committed
93 94
                                                         HttpServletRequest request) {
        Map<String, Object> resultMap = new LinkedHashMap<>();
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
//        String captchaId = request.getHeader("CaptchaId");
//        if (StringUtils.isNotBlank(captcha)) {
//            if (StringUtils.isNotBlank(captchaId)) {
//                String uuidCap = stringRedisTemplate.opsForValue().get(captchaId);
//                if (StringUtils.isNotBlank(uuidCap)) {
//                    if (!uuidCap.trim().equalsIgnoreCase(captcha.trim())) {
//                        stringRedisTemplate.delete(captchaId);
//                        resultMap.put("status", 400);
//                        resultMap.put("message", "验证码不正确!");
//                        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resultMap);
//                    }
//                } else {
//                    stringRedisTemplate.delete(captchaId);
//                    resultMap.put("status", 400);
//                    resultMap.put("message", "验证码已失效,请刷新页面!");
//                    return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resultMap);
//                }
//            } else {
//                //stringRedisTemplate.delete(captchaId);
//                resultMap.put("status", 400);
//                resultMap.put("message", "验证码获取失败!");
//                return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resultMap);
//            }
//        } else {
//            stringRedisTemplate.delete(captchaId);
//            resultMap.put("status", 400);
//            resultMap.put("message", "验证码不能为空!");
//            return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(resultMap);
//        }
//        stringRedisTemplate.delete(captchaId);

        TUser user;
liqin's avatar
liqin committed
127
        if (StringUtils.isNoneBlank(username)) {
wzp's avatar
wzp committed
128 129

            try {
liqin's avatar
liqin committed
130 131 132
            //访问一次,计数一次
            ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
            if ("LOCK".equals(opsForValue.get(SHIRO_IS_LOCK + username))) {
wzp's avatar
wzp committed
133
                resultMap.put("resultCode", "500");
wzp's avatar
wzp committed
134
                resultMap.put("message", "由于密码输入错误次数大于5次,12小时内帐号已禁止登录!请您联系相关管理人员。");
liqin's avatar
liqin committed
135 136 137
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(resultMap);
            }

138 139
            user = userService.selectByUsername(username);
            if (user == null) {
wzp's avatar
wzp committed
140
                resultMap.put("resultCode", "500");
liqin's avatar
liqin committed
141 142 143 144
                resultMap.put("message", "用户名或密码不正确!");
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(resultMap);
            }

wzp's avatar
wzp committed
145
            if (AuditOperationEnum.DISABLE.name().equals(user.getStatus())) {
wzp's avatar
wzp committed
146 147 148
                resultMap.put("resultCode", "500");
                resultMap.put("message", "此帐号已禁用,请联系管理员!");
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(resultMap);
liqin's avatar
liqin committed
149 150
            }

wzp's avatar
wzp committed
151 152
            if (user.getPermanent()!=null&&!user.getPermanent()) {
                if (user.getEffectiveDate().isAfter(LocalDate.now())||user.getExiredDate().isBefore(LocalDate.now())) {
wzp's avatar
wzp committed
153 154 155
                    resultMap.put("resultCode", "500");
                    resultMap.put("message", "此帐号已失效,请联系管理员!");
                    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(resultMap);
wzp's avatar
wzp committed
156 157 158
                }
            }

159 160 161
                byte[] salt = user.getPasswordSalt();
                String s1 = new String(SHA256PasswordEncryptionService.createPasswordHash(password, salt));
                if (!new String(SHA256PasswordEncryptionService.createPasswordHash(password, salt)).equals(new String(user.getPasswordHash()))) {
liqin's avatar
liqin committed
162 163 164 165 166 167 168 169 170 171 172
                    opsForValue.increment(SHIRO_LOGIN_COUNT + username, 1);
                    //计数大于5时,设置用户被锁定一小时
                    String s = opsForValue.get(SHIRO_LOGIN_COUNT + username);
                    if (StringUtils.isNotBlank(s)) {
                        if (Integer.parseInt(s) >= 5) {
                            opsForValue.set(SHIRO_IS_LOCK + username, "LOCK");
                            stringRedisTemplate.expire(SHIRO_IS_LOCK + username, 12, TimeUnit.HOURS);
                        }
                    }
                    throw new IncorrectCredentialsException("用户名或密码不正确!");
                }
wzp's avatar
wzp committed
173
                List<Role> roles = roleService.selectRoleByUserId(user.getId());
wzp's avatar
wzp committed
174
                List<String> list1 = new ArrayList<>();
175 176
                //获取当前用户角色拥有菜单
                List<Menu> userMenuPerms = new ArrayList<>();
wzp's avatar
wzp committed
177 178 179
                if (roles!=null&&roles.get(0)!=null) {
                    roles.stream().forEach(r -> list1.add(r.getId()));
                    user.setRoleList(list1);
wzp's avatar
wzp committed
180
                    userMenuPerms = this.menuService.getUserMenuPerms(list1);
181
                }
liqin's avatar
liqin committed
182 183 184

                //登录时插入系统日志
                String operationContent = username + "登录本系统";
185 186
                if (user.getOrgName() != null) {
                    operationContent += ",机构" + user.getOrgName();
liqin's avatar
liqin committed
187
                }
188
                this.sysLogController.insertSysLog(operationContent, username, user.getId());
liqin's avatar
liqin committed
189

190
                String token = JwtTokenUtil.sign(username, user.getId());
liqin's avatar
liqin committed
191
                // 将token信息存入Redis
192
                stringRedisTemplate.opsForValue().set(SHIRO_JWT_TOKEN + token, user.getId(), 240, TimeUnit.MINUTES);
liqin's avatar
liqin committed
193

194
                resultMap.put("user", user);
liqin's avatar
liqin committed
195 196
                resultMap.put("token", token);
                resultMap.put("menuList", userMenuPerms);
wzp's avatar
wzp committed
197
                resultMap.put("resultCode", "200");
liqin's avatar
liqin committed
198
                resultMap.put("message", "登录成功");
wzp's avatar
wzp committed
199
                return ResponseEntity.ok(resultMap);
liqin's avatar
liqin committed
200
            } catch (Exception e) {
wzp's avatar
wzp committed
201
                resultMap.put("resultCode", "500");
liqin's avatar
liqin committed
202 203 204 205 206 207 208
                resultMap.put("message", e.getMessage());
            }
        }
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(resultMap);
    }

    @RequestMapping(value = "logout", method = RequestMethod.GET)
wzp's avatar
wzp committed
209 210
    public ResponseEntity<JSONObject> logout() {
        String token = request.getHeader("Authorization");
liqin's avatar
liqin committed
211 212
        try {
            if (StringUtils.isNotBlank(token)) {
wzp's avatar
wzp committed
213
//                SecurityUtils.getSubject().logout();
liqin's avatar
liqin committed
214 215
                this.stringRedisTemplate.delete(SHIRO_JWT_TOKEN + token);
            }
liqin's avatar
liqin committed
216
            JSONObject resultMap = new JSONObject();
wzp's avatar
wzp committed
217
            resultMap.put("resultCode", "200");
liqin's avatar
liqin committed
218 219
            resultMap.put("message", "成功");
            resultMap.put("data", "");
wzp's avatar
wzp committed
220
            return ResponseEntity.ok(resultMap);
liqin's avatar
liqin committed
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
        } catch (Exception e) {
            LOGGER.error("注销错误!", e);
        }
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    }

    @RequestMapping(value = {"/verifyCode"}, method = {RequestMethod.GET})
    public void verifyCode(HttpServletRequest request, HttpServletResponse response, Integer width, Integer height) {
        String uuid = UUID.randomUUID().toString();
        try {
            SpecCaptcha iVerifyCodeGen;
            if ((width != null && width > 0) && (height != null && height > 0)) {
                iVerifyCodeGen = new SpecCaptcha(width, height);
            } else {
                iVerifyCodeGen = new SpecCaptcha();
            }
            response.addHeader("CaptchaId", uuid);
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0L);
            response.setContentType("image/jpeg");
            String out = iVerifyCodeGen.out(response.getOutputStream());
            this.stringRedisTemplate.opsForValue().set(uuid, out, 1800L);
        } catch (IOException e) {
            LOGGER.info("", e);
        }
    }

    @RequestMapping(value = {"/verifyCode1"}, method = {RequestMethod.GET}, produces = MediaType.IMAGE_JPEG_VALUE)
liqin's avatar
liqin committed
250 251
    public @ResponseBody
    byte[] verifyCode1(HttpServletRequest request, HttpServletResponse response, Integer width, Integer height) {
liqin's avatar
liqin committed
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
        String uuid = UUID.randomUUID().toString();
        ByteArrayOutputStream baos = null;
        try {
            SpecCaptcha iVerifyCodeGen;
            if ((width != null && width > 0) && (height != null && height > 0)) {
                iVerifyCodeGen = new SpecCaptcha(width, height);
            } else {
                iVerifyCodeGen = new SpecCaptcha();
            }
            response.setHeader("Pragma", "no-cache");
            response.setHeader("Cache-Control", "no-cache");
            response.setDateHeader("Expires", 0L);
            response.setHeader("Access-Control-Allow-Headers", "CaptchaId");
            response.setHeader("Access-Control-Expose-Headers", "CaptchaId");
            response.addHeader("CaptchaId", uuid);

            baos = new ByteArrayOutputStream();
            String out = iVerifyCodeGen.out(baos);
            this.stringRedisTemplate.opsForValue().set(uuid, out, 1800L);
            return baos.toByteArray();
        } catch (Exception e) {
            LOGGER.info("", e);
        } finally {
            if (baos != null) {
                try {
                    baos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

}