• 认证和授权学习1基于session的认证授权流程


    认证和授权学习1基于session的认证授权流程

    一、什么是认证

    用户认证就是判断一个用户的身份是否合法的过程,用户去访问系统资源时系统要求验证用户的身份信 息,身份合法方可继续访问,不合法则拒绝访问

    二、什么是授权

    授权是用户认证通过后,根据用户的权限来控制用户对访问资源的过程,拥有资源的访问权限则正常访问,没有 权限则拒绝访问。

    授权可以理解为主体(用户)对资源的受限操作

    三、基于session的认证授权流程

    用户携带账号密码请求登录,登录成功后服务端生成用户信息对象保存在session中,把sessionId存到cookie中返回给客户端;当客户端再次访问时携带cookie信息,服务端判断session中是否存有用户信息,如果没有表示未登录,如果有根据session中用户信息的权限信息完成授权。用户退出时清空session信息

    用户登录时携带的账号密码等信息可以封装到一个参数对象中,

    
    /**
     * 认证请求参数
     */
    @Data
    public class AuthenticationRequest {
    
        /**
         * 用户名
         */
        private String username;
        /**
         * 密码
         */
        private String password;
    }
    

    登录成功后存放到session中的用户信息也可以定义一个对象

    
    /**
     * 当前登录用户信息
     */
    @Data
    @AllArgsConstructor
    public class UserDto {
        public final static String SESSION_USER_KEY ="_USER";
        private String id;
        private String username;
        private String password;
        private String fullname;
        private String mobile;
        /**
         * 用户权限
         */
        private Set<String> authorities;
    }
    

    可以定义一个校验接口来校验用户是否能登录成功

    
    /**
     * 认证服务
     */
    public interface AuthenticationService {
        /**
         * 用户认证
         * @param authenticationRequest 用户认证请求
         * @return 认证成功的用户信息
         */
        UserDto authentication(AuthenticationRequest authenticationRequest);
    }
    

    校验方法的实现

    @Override
    public UserDto authentication(AuthenticationRequest authenticationRequest) {
            if (authenticationRequest == null
                    || StringUtils.isEmpty(authenticationRequest.getUsername())
                    || StringUtils.isEmpty(authenticationRequest.getPassword())) {
                throw new RuntimeException("账号或密码为空");
            }
            UserDto userDto = getUserDto(authenticationRequest.getUsername());
            if (userDto == null) {
                throw new RuntimeException("查询不到该用户");
            }
            if (!authenticationRequest.getPassword().equals(userDto.getPassword())) {
                throw new RuntimeException("账号或密码错误");
            }
            return userDto;
        }
    

    其中getUserDto方法用来根据传入的用户名到数据库中查询用户对象

    定义一个controller来处理登录请求

    @RestController
    public class LoginController {
    
        @Autowired
        private AuthenticationService authenticationService;
    
        @PostMapping(value = "/login",produces = {"text/plain;charset=UTF-8"})
        public String login(AuthenticationRequest authenticationRequest, HttpServletRequest request){
            UserDto userDto = authenticationService.authentication(authenticationRequest);
            //登录成功后把当前用户信息保存到session中
            request.getSession().setAttribute(UserDto.SESSION_USER_KEY,userDto);
            return userDto.getFullname()+"登录成功";
        }
    
        @GetMapping( value = "/logout",produces = {"text/plain;charset=UTF-8"})
        public String logout(HttpServletRequest request){
            //让session失效
            request.getSession().invalidate();
            return "退出成功";
        }
    }
    

    这样就完成了用户的认证过程。在用户访问某个系统资源时需要判断是否有对应的权限,即授权流程,可以通过springmvc的拦截器来对请求进行拦截

    
    /**
     * 权限控制拦截器
     */
    @Component
    public class AuthenticationInterceptor implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            //读取会话信息
            Object object = request.getSession().getAttribute(UserDto.SESSION_USER_KEY);
            if (null == object) {
                writeContent(response, "请登录");
            }
    
            UserDto user = (UserDto) object;
            //请求的url
            String requestURI = request.getRequestURI();
    
            //对r1和r2两个资源的访问进行控制
            if(user.getAuthorities().contains("p1") && requestURI.contains("/r1")){
                return true;
            }
            if(user.getAuthorities().contains("p2") && requestURI.contains("/r2")){
                return true;
            }
            writeContent(response,"权限不足,拒绝访问");
            return false;
        }
    
        //向前端响应信息
        private void writeContent(HttpServletResponse response, String msg) throws IOException {
            response.setContentType("text/plain;charset=UTF-8");//注意这个utf-8要是大写,小写的时候前端会乱码
            PrintWriter writer = response.getWriter();
            writer.print(msg);
            writer.close();
            response.resetBuffer();
        }
    }
    

    配置这个自定义拦截器到系统中,并指定拦截路径为需要受保护的资源路径,如/r/**,这样当用户访问/r/r1或者/r/r2时就会被拦截到,并判断是否有对应的权限,如果有权限,可以正常访问,即对用户完成了授权,没有权限就拒绝访问表示不进行授权。

    对访问请求的拦截也可以通过过滤器来实现,道理都是一样的。

  • 相关阅读:
    系统分析记录rocketmq导致jvm线程数量大
    值得被提拔的人,往往具备以下几点特质
    上周热点回顾(7.187.24)
    上周热点回顾(8.18.7)
    上周热点回顾(7.47.10)
    上周热点回顾(8.88.14)
    上周热点回顾(7.117.17)
    上周热点回顾(8.158.21)
    下一步,敏捷!| 助力远程办公走向成功系列讲座
    上周热点回顾(7.257.31)
  • 原文地址:https://www.cnblogs.com/chengxuxiaoyuan/p/13798882.html
Copyright © 2020-2023  润新知