素材巴巴 > 程序开发 >

Spring Security OAuth2.0(2):基于session的认证方式

程序开发 2023-09-03 12:13:30

文章目录

认证流程

qquad 基于session的认证方式如下
qquad 它的交互流程是,用户认证成功后,在服务端生成用户相关的数据保存在session(当前会话)中,发给客户端的session_id存放到cookie中,这样用户客户端请求时带上session_id就可以验证服务器端是否存在session数据,以此完成用户的合法验证,当用户退出系统或session过期销毁时,客户端的session_id也就无效了。
在这里插入图片描述
基于Session的认证机制由Servlet规范定制,Servlet容器已实现,用户通过HttpSession的操作方式即可实现,如下是HttpSession相关的操作API。

方法解释HttpSession getSession(Boolean create)获取当前HttpSession对象void setAttribute(String name,Object value)向当前session中存储对象Object getAttribute(String name)从session中取对象void removeAttribue(String name)移除session中的对象void invalidate()使HttpSession失效

创建工程

案例使用maven构建,使用SpringMVC,Servlet3.0实现。

本章代码已分享至Gitee: https://gitee.com/lengcz/security-springmvc

1 创建maven工程

结构预览
在这里插入图片描述

(1)选择maven(不选择maven模板),创建maven工程
在这里插入图片描述
(2)配置pom文件
在这里插入图片描述


 4.0.0com.it2security-springmvc1.0-SNAPSHOTwarUTF-81.81.8org.springframeworkspring-webmvc5.1.5.RELEASEjavax.servletjavax.servlet-api3.0.1providedorg.projectlomboklombok1.16.12security-springmvcorg.apache.tomcat.maventomcat7-maven-plugin2.2org.apache.maven.pluginsmaven-compiler-plugin1.81.8maven-resources-pluginutf-8truesrc/main/resourcestrue**/*src/main/javatrue**/*.xml
 

(3) Spring容器配置
在config包下定义ApplicationConfig.java,它对应web.xml中ContextLoaderListener的配置

/*** config包下定义ApplicationConfig.java,它对应web.xml中ContextLoaderListener的配置*/
 @Configuration  //相当于ApplicationContext.xml
 @ComponentScan(basePackages = "com.it2.security.springmvc",excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class)})
 public class ApplicationConfig {//在此配置除了Controller的其它bean,比如:数据库连接池,事务管理器,业务bean等}
 

(4) servletContext配置
本案例采用Servlet3.0无web.xml方式,在config包下定WebConfig.java,它对应DispatcherServlet配置

@Configuration //相当于springmvc.xml
 @EnableWebMvc
 @ComponentScan(basePackages = "com.it2.security.springmvc",includeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = Controller.class)})
 public class WebConfig implements WebMvcConfigurer {//视图解析器@Beanpublic InternalResourceViewResolver viewResolver() {InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();viewResolver.setPrefix("/WEB-INF/view/");viewResolver.setSuffix(".jsp");return viewResolver;}@Autowiredprivate SimpleAuthenticationInterceptor simpleAuthenticationInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(simpleAuthenticationInterceptor).addPathPatterns("/r/**");}
 }
 

(5)加载Spring容器
在init包下定义Spring容器初始化类SpringApplicationInitializer,此类实现WebApplicationInitializer接口,Spring容器加载启动时加载WebApplicationInitializer接口的所有实现类。


 public class SpringApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {//spring容器@Overrideprotected Class[] getRootConfigClasses() {return new Class[]{ApplicationConfig.class};}//servletContext@Overrideprotected Class[] getServletConfigClasses() {return new Class[]{WebConfig.class};}//url-mapping@Overrideprotected String[] getServletMappings() {return new String[]{"/"};}
 }
 

2. 实现认证功能

(1) 在view目录下编写一个登录页面,login.jsp
在这里插入图片描述

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="utf-8" %>
 
 登录
 
 
 
用户名:
密码:

(2) 在WebConfig.java中配置,将根目录指向登录页

//指向登录页面@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/").setViewName("login");}
 

(3) 编写登录认证接口
用户进入认证页面后,输入账号和密码,点击登录,请求/login进行身份认证。

public interface AuthenticationService {/*** 用户认证** @param authenticationRequest* @return*/UserDto authentication(AuthenticationRequest authenticationRequest);
 }
 

认证请求实体和返回实体

/*** 认证请求参数*/
 @Data
 public class AuthenticationRequest {private String username;private String password;}
 
/*** 用户信息*/
 @NoArgsConstructor
 @AllArgsConstructor
 @Data
 public class UserDto {public static final String SESSION_USER_KEY = "_user";private String id;private String username;private String password;private String fullname;private String mobile;/*** 用户权限*/private Set authorities;}

(3) 编写校验实现类

package com.it2.security.springmvc.service;import com.it2.security.springmvc.model.AuthenticationRequest;
 import com.it2.security.springmvc.model.UserDto;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;@Service
 public class AuthenticationServiceImpl implements AuthenticationService {@Overridepublic UserDto authentication(AuthenticationRequest authenticationRequest) {if (null == authenticationRequest || StringUtils.isEmpty(authenticationRequest.getUsername()) ||StringUtils.isEmpty(authenticationRequest.getPassword())) {throw new RuntimeException("账号或密码不能为空");}UserDto userDto = getUserDto(authenticationRequest.getUsername());if (null == userDto) {throw new RuntimeException("用户不存在");}if (!authenticationRequest.getPassword().equals(userDto.getPassword())) {throw new RuntimeException("密码错误");}return userDto;}public UserDto getUserDto(String username) {return userMap.get(username);}private Map userMap = new HashMap<>();{Set authorities1 = new HashSet<>();authorities1.add("p1");Set authorities2 = new HashSet<>();authorities2.add("p2");userMap.put("xiaowang", new UserDto("10", "xiaowang", "123456", "小王", "13800000000", authorities1));userMap.put("xiaoyu", new UserDto("11", "xiaoyu", "111111", "小鱼", "13900000000", authorities2));}
 }

(4) 定义登录接口

@RestController
 public class LoginController {@AutowiredAuthenticationService authenticationService;@RequestMapping(value = "/login", produces = "text/plain;charset=utf-8")public String login(AuthenticationRequest authenticationRequest, HttpSession session) {UserDto userDto = authenticationService.authentication(authenticationRequest);session.setAttribute(UserDto.SESSION_USER_KEY, userDto);return userDto.getUsername() + "登录成功";}@RequestMapping(value = "/logout", produces = "text/plain;charset=utf-8")public String logout(AuthenticationRequest authenticationRequest, HttpSession session) {session.invalidate();return "登出成功";}
 }    

(5)配置启动

#启动命令
 clean tomcat7:run
 

在这里插入图片描述
(6) 启动服务测试
在这里插入图片描述

在这里插入图片描述

3. 会话功能

在上面,在登录成功会将用户存入session,在访问资源时getSession获取用户身份信息,在登出时,使session 无效已完成会话。
在这里插入图片描述

4. 授权功能

(1)首先给用户添加权限
在这里插入图片描述
在这里插入图片描述

(2)定义拦截器,用于处理权限

//权限拦截
 @Component
 public class SimpleAuthenticationInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//取出用户信息,判断请求的url是否在用户的权限范围内String requestURI = request.getRequestURI();Object object = request.getSession().getAttribute(UserDto.SESSION_USER_KEY);if (null == object) {writeContent(response, "请登录");return false;}UserDto userDto = (UserDto) object;Set authorities = userDto.getAuthorities();if (authorities.contains("p1") && requestURI.contains("/r/r1")) {return true;}if (authorities.contains("p2") && requestURI.contains("/r/r2")) {return true;}writeContent(response, "没有权限");return false;}private void writeContent(HttpServletResponse response, String msg) throws IOException {response.setContentType("text/html;charset=utf-8");PrintWriter writer = response.getWriter();writer.print(msg);writer.close();}
 }
 

(3)在WebConfig.java注册拦截器

    @Autowiredprivate SimpleAuthenticationInterceptor simpleAuthenticationInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(simpleAuthenticationInterceptor).addPathPatterns("/r/**");}
 

(4)启动服务测试,登录xiaowang账号,访问资源测试,分别方位r2和r1,可以看到xiaowang在访问r2时没有权限,而可以访问r1
在这里插入图片描述


标签:

素材巴巴 Copyright © 2013-2021 http://www.sucaibaba.com/. Some Rights Reserved. 备案号:备案中。