shiro(session+redis),基于springboot,基于前后端分离,从登录认证到鉴权

这个demo是基于springboot项目的。

名词介绍:
Shiro
主要分为 安全认证 和 接口授权 两个部分,其中的核心组件为 Subject、 SecurityManager、 Realms,公共部分 Shiro 都已经为我们封装好了,我们只需要按照一定的规则去编写响应的代码即可…
Subject
表示主体,将用户的概念理解为当前操作的主体,因为它即可以是一个通过浏览器请求的用户,也可能是一个运行的程序,外部应用与 Subject 进行交互,记录当前操作用户。Subject 代表了当前用户的安全操作
SecurityManager
则管理所有用户的安全操作。
SecurityManager
即安全管理器,对所有的 Subject 进行安全管理,并通过它来提供安全管理的各种服务(认证、授权等)
Realm
充当了应用与数据安全间的 桥梁 或 连接器。当对用户执行认证(登录)和授权(访问控制)验证时,Shiro 会从应用配置的 Realm 中查找用户及其权限信息。

项目结构
在这里插入图片描述

1.导入shiro依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
<!--juint-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
<!--starter-web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
<!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
<!--connector-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
<!--jdbc的启动器,默认使用HikariCP连接池-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
<!--mybatis_plus-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <dependency>
            <groupId>org.freemarker</groupId>
            <artifactId>freemarker</artifactId>
            <version>2.3.30</version>
        </dependency>
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>3.4.1</version>
        </dependency>
<!--shiro -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.7.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.crazycake</groupId>
            <artifactId>shiro-redis</artifactId>
            <version>2.8.24</version>
        </dependency>
<!--commons-lang3-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.9</version>
        </dependency>
<!--swagger 2-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>

将用户信息交给redis管理
使用swagger2

2.shiro配置类

import com.example.shirospringboot.realm.UserRealm;
import com.example.shirospringboot.shiro.MySessionManager;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * shiro中文学习
 * https://www.w3cschool.cn/shiro/xgj31if4.html
 */

/**
 * 测试role,permission的时候,手动删除旧的redis键值对
 */
@Configuration
public class ShiroConfig {

    @Autowired
    private RedisManager redisManager;
    @Autowired
    private RedisSessionDAO redisSessionDAO;
    @Autowired
    private RedisCacheManager redisCacheManager;

    @Bean()
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        /**
         * 拦截器
         * anon: 无需认证就可以访问
         * authc: 必须认证才能访问
         * user: 必须拥有记住我功能才能用
         * perms: 拥有对某个资源的权限才能访问
         * role: 拥有某个角色权限才能访问
         */
        Map<String, String> filterChainDefinitionMap =new LinkedHashMap<>();
        filterChainDefinitionMap.put("/login","anon");
        filterChainDefinitionMap.put("/logout","anon");
        /**
         * 使用权限注解的不需要在这里加,如/test
         * filterChainDefinitionMap .put("/test","authc");
         */
        //放行Swagger2页面,需要放行这些
        filterChainDefinitionMap.put("/swagger-ui.html","anon");
        filterChainDefinitionMap.put("/swagger/**","anon");
        filterChainDefinitionMap.put("/webjars/**", "anon");
        filterChainDefinitionMap.put("/swagger-resources/**","anon");
        filterChainDefinitionMap.put("/v2/**","anon");
        filterChainDefinitionMap.put("/static/**", "anon");

        filterChainDefinitionMap .put("/**","authc");
        shiroFilterFactoryBean.setLoginUrl("/login");
        shiroFilterFactoryBean.setUnauthorizedUrl("/login");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");//散列算法:这里使用MD5算法;
        hashedCredentialsMatcher.setHashIterations(1024);//散列的次数
        hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);
        return hashedCredentialsMatcher;
    }
    @Bean()
    public UserRealm userRealm() {
        UserRealm userRealm = new UserRealm();
        userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
        return userRealm;
    }
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(){
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm(userRealm());
        // 自定义session管理 使用redis
        defaultWebSecurityManager.setSessionManager(sessionManager());
        // 自定义缓存实现 使用redis
        defaultWebSecurityManager.setCacheManager(redisCacheManager);
        return defaultWebSecurityManager;
    }
    @Bean
    public SessionManager sessionManager() {
        MySessionManager mySessionManager = new MySessionManager();
        mySessionManager.setSessionDAO(redisSessionDAO);
        return mySessionManager;
    }

    /**
     * 开启shiro权限注解
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        autoProxyCreator.setProxyTargetClass(true);
        return autoProxyCreator;
    }
}

3.ShiroRedis配置类

application.properties

spring.redis.shiro.host=127.0.0.1
spring.redis.shiro.port=6379
spring.redis.shiro.timeout=5000
#没有密码写了会报错
#spring.redis.shiro.password=123456
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class ShiroRedisConfig {
    @Value("${spring.redis.shiro.host}")
    private String host;
    @Value("${spring.redis.shiro.port}")
    private int port;
    @Value("${spring.redis.shiro.timeout}")
    private int timeout;
//    @Value("${spring.redis.shiro.password}")
//    private String password;

    @Bean
    public RedisManager redisManager() {
        RedisManager redisManager = new RedisManager();
        redisManager.setHost(host);
        redisManager.setPort(port);
        redisManager.setExpire(1800);// 配置缓存过期时间
        redisManager.setTimeout(timeout);
//        redisManager.setPassword(password);
        return redisManager;
    }
    @Bean
    public RedisCacheManager redisCacheManager() {
        RedisCacheManager redisCacheManager = new RedisCacheManager();
        redisCacheManager.setRedisManager(redisManager());
        return redisCacheManager;
    }
    @Bean
    public RedisSessionDAO redisSessionDAO() {
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
        redisSessionDAO.setRedisManager(redisManager());
        return redisSessionDAO;
    }
}

4.Swagger配置类

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@EnableSwagger2
@Configuration
public class SwaggerConfig {

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                /**
                 * Swagger会扫描该包下所有Controller定义的API,并产生文档内容(除了被@ApiIgnore注解的API)
                 */
                .apis(RequestHandlerSelectors.basePackage("com.example.shirospringboot.controller"))
                /**
                 * 可以根据url路径设置哪些请求加入文档,忽略哪些请求
                 */
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Shiro-Springboot Swagger2 APIs")
                .description("shiro-springboot项目controller接口文档")
                .version("1.0")
                .build();
    }
}

5.安全认证和权限验证的核心,自定义Realm

import com.example.shirospringboot.entity.User;
import com.example.shirospringboot.service.impl.UserServiceImpl;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.Set;

public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserServiceImpl userService;

    /**
     * 认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        /**
         * 获取当前登录的主题
          */
        String username = (String) token.getPrincipal();
        User user = userService.getUserByUserName(username);
        if(user==null){
            throw new AuthenticationException();
        }
        String credentials = user.getPassword();
        ByteSource credentialsSalt = ByteSource.Util.bytes(user.getSalt());
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                user.getUsername(), //用户名
                credentials, //密码
                credentialsSalt,
                getName()  //当前realm对象的name,调用父类的getName()方法即可
        );
        Session session = SecurityUtils.getSubject().getSession();
        session.setAttribute("USER_SESSION", user);
        return authenticationInfo;

        /**
         *         String name="zhujie",password="123",salt= SaltUtil.getSalt();
         *         System.out.println("salt:"+salt);
         *         ByteSource saltByteSource = ByteSource.Util.bytes(salt);
         *         String newPs = new SimpleHash("MD5", password, salt, 1024).toHex();
         *         System.out.println("saltByteSource:"+saltByteSource);
         *         System.out.println("密码:"+newPs);
         */
    }
    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        Session session = SecurityUtils.getSubject().getSession();
        System.out.println("授权方法获取用户:"+session.getAttribute("USER_SESSION"));
        User user = (User) session.getAttribute("USER_SESSION");
        Set<String> roleSet = new HashSet<>();
        Set<String> permissionSet = new HashSet<>();
        userService.getUserRoles(user.getUsername()).forEach(role -> roleSet.add(role.getName()));
        userService.getUserPermissions(user.getUsername()).forEach(permission -> permissionSet.add(permission.getName()));
        info.setRoles(roleSet);
        info.setStringPermissions(permissionSet);
        return info;
    }
}

6.全局异常处理器

import com.example.shirospringboot.Result.Result;
import com.example.shirospringboot.Result.ResultUtil;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.ExpiredCredentialsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 如果身份验证失败请捕获 AuthenticationException 或其子类,常见的如:
     * DisabledAccountException(禁用的帐号)、
     * LockedAccountException(锁定的帐号)、
     * UnknownAccountException(错误的帐号)、
     * ExcessiveAttemptsException(登录失败次数过多)、
     * IncorrectCredentialsException (错误的凭证)、
     * ExpiredCredentialsException(过期的凭证)等
     * 具体请查看其继承关系;
     * 对于页面的错误消息展示,最好使用如 “用户名 / 密码错误” 而不是 “用户名错误”/“密码错误”,防止一些恶意用户非法扫描帐号库;
     */

    //无权限
    @ExceptionHandler(value = UnauthorizedException.class)
    public Result handler(UnauthorizedException e) {
        return ResultUtil.NO_PERMISSION();
    }
    //身份过期
    @ExceptionHandler(value = ExpiredCredentialsException.class)
    public Result handler(ExpiredCredentialsException e) {
        return ResultUtil.IDENTITY_EXPIRED();
    }
    //没有登陆
    @ExceptionHandler(value = UnauthenticatedException.class)
    public Result handler(UnauthenticatedException e) {
        return ResultUtil.NOT_LOGGED_IN();
    }
    //密码错误
    @ExceptionHandler(value = IncorrectCredentialsException.class)
    public Result handler(IncorrectCredentialsException e) {
        return ResultUtil.INCORRECT_PASSWORD();
    }
    //用户不存在
    @ExceptionHandler(value = AuthenticationException.class)
    public Result handler(AuthenticationException e) {
        return ResultUtil.USER_NOT_FOUND();
    }
    //账号冻结
    @ExceptionHandler(value = LockedAccountException.class)
    public Result handler(LockedAccountException e) {
        return ResultUtil.ACCOUNT_FREEZING();
    }

}

7.因为现在的项目大多都是前后端分离的,所以我们需要实现自己的session管理

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.Serializable;


public class MySessionManager extends DefaultWebSessionManager {

    private static final String TOKEN = "token";
    private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";

    public MySessionManager() {
        super();
    }

    @Override
    protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
        String id = WebUtils.toHttp(request).getHeader(TOKEN);
        //如果请求头中有 token 则其值为sessionId
        if (!StringUtils.isEmpty(id)) {
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
            return id;
        } else {
            //否则按默认规则从cookie取sessionId
            return super.getSessionId(request, response);
        }
    }
}

8.控制器

import com.example.shirospringboot.Result.Result;
import com.example.shirospringboot.Result.ResultUtil;
import com.example.shirospringboot.entity.User;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;

@Api(value="LoginController|登录控制器")
@RestController
@RequestMapping("/")
public class LoginController {
    @ApiOperation(value = "用户登录接口", notes = "提供用户名和密码")
    @PostMapping("/login")
    public Result login(@ApiParam(name = "user",value = "登录用户",required = true) @RequestBody User user){
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
        Subject subject = SecurityUtils.getSubject();
        HashMap<String, Object> map = new HashMap<>();
        try {
            subject.login(token);
            map.put("token", subject.getSession().getId());
        } catch (IncorrectCredentialsException e) {
            //密码错误
            throw e;
        } catch (LockedAccountException e) {
            //冻结
            throw e;
        } catch (AuthenticationException e) {
            //用户不存在
            throw e;
        } catch (Exception e) {
            return ResultUtil.EXCEPTION_UNKNOWN();
        }
        System.out.println(user.getUsername()+"已登录");
        return ResultUtil.SUCCESS("登陆成功",null);
    }

    @ApiOperation("用户登出接口")
    @GetMapping("/logout")
    public Result logout(){
        SecurityUtils.getSubject().logout();
        return ResultUtil.SUCCESS("已退出登录",null);
    }

    @ApiOperation("用户权限测试接口")
    @GetMapping("/test")
    @RequiresRoles(value = {"admin"})
    @RequiresPermissions(value = {"order:query:zhujie"})
    public Result test(){
        return ResultUtil.SUCCESS("test",null);
    }

}

常用注解
@RequiresGuest 代表无需认证即可访问,同理的就是 /path=anon
@RequiresAuthentication 需要认证,只要登录成功后就允许你操作
@RequiresPermissions 需要特定的权限,没有则抛出 AuthorizationException
@RequiresRoles 需要特定的橘色,没有则抛出 AuthorizationException

9.以上就是shiro登陆和鉴权的主要配置和类,下面补充一下其他信息。

因为数据是模拟的,所以在登陆认证的时候,并没有通过数据库查用户信息,可以通过以下方式模拟加密后的密码:

         String name="zhujie",password="123",salt= SaltUtil.getSalt();
         System.out.println("salt:"+salt);  //数据库salt字段
         ByteSource saltByteSource = ByteSource.Util.bytes(salt);
         String newPs = new SimpleHash("MD5", password, salt, 1024).toHex();
         System.out.println("saltByteSource:"+saltByteSource);
         System.out.println("密码:"+newPs);  // 数据库password字段
    }

UserService添加两个方法,便于调用。

public interface IUserService extends IService<User> {
    User getUserByUserName(String username);
    List<Role> getUserRoles(String username);
    List<Permission> getUserPermissions(String username);
}
    }

随机生成盐

import java.util.Random;

public class SaltUtil {
    static char[] chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890!@#$%^&*()_+".toCharArray();
    static int length=32;

    public static String getSalt(int saltLength){
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < saltLength; i++){
            /**
             * Random().nextInt()返回值为[0,n)
             */
            char aChar = chars[new Random().nextInt(chars.length)];
            sb.append(aChar);
        }
        return sb.toString();
    }
    public static String getSalt(){
        return getSalt(length);
    }
}

统一结果封装

import io.swagger.annotations.ApiModel;
import lombok.Data;

@Data
@ApiModel("统一封装返回对象")
public class Result<T> {
    /** 错误码. */
    private Integer code;
    /** 提示信息. */
    private String msg;
    /** 具体的内容. */
    private T data;
}
public enum ResultEnum {
    SUCCESS(200, "操作成功"),
    EXCEPTION_NOT_LOGGED_IN(401, "未登录,请登录"),
    EXCEPTION_USER_NOT_FOUND(401,"用户不存在"),
    EXCEPTION_INCORRECT_PASSWORD(401,"密码错误"),
    EXCEPTION_IDENTITY_EXPIRED(401, "身份已过期,请重新登录"),
    EXCEPTION_ACCOUNT_FREEZING(401, "账号已被冻结"),
    EXCEPTION_NO_PERMISSION(402, "无权限操作"),
    EXCEPTION_UNKNOWN(400, "未知异常");

    private Integer code;
    private String msg;

    ResultEnum(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    public Integer getCode() {
        return code;
    }
    public String getMsg() {
        return msg;
    }
}

import org.apache.commons.lang3.StringUtils;

public class ResultUtil {
    /**
     * 成功
     */
    public static Result SUCCESS(String message,Object object) {
        Result result = new Result();
        result.setCode(ResultEnum.SUCCESS.getCode());
        if(StringUtils.isBlank(message)){
            result.setMsg(ResultEnum.SUCCESS.getMsg());
        }else{
            result.setMsg(message);
        }
        result.setData(object);
        return result;
    }
    public static Result SUCCESS() {
        return SUCCESS(null,null);
    }
    /**
     * 未登录
     */
    public static Result NOT_LOGGED_IN() {
        Result result = new Result();
        result.setCode(ResultEnum.EXCEPTION_NOT_LOGGED_IN.getCode());
        result.setMsg(ResultEnum.EXCEPTION_NOT_LOGGED_IN.getMsg());
        return result;
    }
    /**
     * 用户不存在
     */
    public static Result USER_NOT_FOUND() {
        Result result = new Result();
        result.setCode(ResultEnum.EXCEPTION_USER_NOT_FOUND.getCode());
        result.setMsg(ResultEnum.EXCEPTION_USER_NOT_FOUND.getMsg());
        return result;
    }
    /**
     * 密码错误
     */
    public static Result INCORRECT_PASSWORD() {
        Result result = new Result();
        result.setCode(ResultEnum.EXCEPTION_INCORRECT_PASSWORD.getCode());
        result.setMsg(ResultEnum.EXCEPTION_INCORRECT_PASSWORD.getMsg());
        return result;
    }
    /**
     * 身份失效
     */
    public static Result IDENTITY_EXPIRED() {
        Result result = new Result();
        result.setCode(ResultEnum.EXCEPTION_IDENTITY_EXPIRED.getCode());
        result.setMsg(ResultEnum.EXCEPTION_IDENTITY_EXPIRED.getMsg());
        return result;
    }
    /**
     * 无权限
     */
    public static Result NO_PERMISSION() {
        Result result = new Result();
        result.setCode(ResultEnum.EXCEPTION_NO_PERMISSION.getCode());
        result.setMsg(ResultEnum.EXCEPTION_NO_PERMISSION.getMsg());
        return result;
    }
    /**
     * 无权限
     */
    public static Result ACCOUNT_FREEZING() {
        Result result = new Result();
        result.setCode(ResultEnum.EXCEPTION_ACCOUNT_FREEZING.getCode());
        result.setMsg(ResultEnum.EXCEPTION_ACCOUNT_FREEZING.getMsg());
        return result;
    }
    /**
     * 未知异常
     */
    public static Result EXCEPTION_UNKNOWN() {
        Result result = new Result();
        result.setCode(ResultEnum.EXCEPTION_UNKNOWN.getCode());
        result.setMsg(ResultEnum.EXCEPTION_UNKNOWN.getMsg());
        return result;
    }
}

10.出现的问题

问题1

<!--        引入devtools之后,项目会用一个base类加载器来加载不改变的类,而会用restart类加载器来加载改变的类。当项目产生修改时,base类加载器不变化,而restart类会重建。类修改时,只对修改过的类重新加载,使得项目重新启动时速度极快。-->
<!--        <dependency>-->
<!--            <groupId>org.springframework.boot</groupId>-->
<!--            <artifactId>spring-boot-devtools</artifactId>-->
<!--            <scope>runtime</scope>-->
<!--            <optional>true</optional>-->
<!--        </dependency>-->
<!--        springboot-test-->

添加以上依赖后,从缓存中读取用户信息会出现cast异常,所以不添加该热部署依赖即可

 User user = (User) session.getAttribute("USER_SESSION");

问题2

放行Swagger2页面

        filterChainDefinitionMap.put("/swagger-ui.html","anon");
        filterChainDefinitionMap.put("/swagger/**","anon");
        filterChainDefinitionMap.put("/webjars/**", "anon");
        filterChainDefinitionMap.put("/swagger-resources/**","anon");
        filterChainDefinitionMap.put("/v2/**","anon");
        filterChainDefinitionMap.put("/static/**", "anon");
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值