登录的面临问题
- 安全问题,登录面临的安全问题
- 用户体验,快捷登录如短信登陆等
- 并发问题 ,用户增加面临很多用户同时登录
- 移动设备登录
- 第三方账号登陆,通过其他社交帐号等其他第三方登录
- 单点登录和统一身份认证,用户需要一次登录访问多个应用程序
- 法律法规和合规性, 登录后数据加密和隐私政策
- 可扩展性和灵活性,登录功能不断扩展和升级可能需要支持
定义:什么是单点登录
简称SSO(Single sign-on)
- 登录后可以访问该系统的各个应用
- 登陆后要存储用户的登陆状态
- 登陆后提供令牌和会话标识
- 存储已有用户的身份凭证
如何实现和解决上面的问题
spring会出手
- 安全问题:Spring Security 是一个强大的安全框架,它提供了多种身份验证和授权机制,可以帮助保护登录功能免受各种安全威胁,如密码泄露、SQL 注入、XSS 和 CSRF 攻击。
- 用户体验问题:Spring 框架提供了丰富的 Web 开发特性,如 Spring MVC 和 Spring WebFlux,可以帮助构建用户友好的登录界面。这些框架提供了灵活的视图解析和模板引擎,允许开发者创建响应式和易于使用的界面。
- 高并发问题:Spring 提供了一系列工具和技术来处理高并发访问,如 Spring Boot 的自动配置和嵌入式服务器,以及 Spring Cloud 中的微服务架构和负载均衡策略。这些特性有助于构建高性能和可扩展的登录系统。
- 移动设备适配:Spring Mobile 是一个针对移动设备优化的扩展,它提供了适配不同移动设备屏幕尺寸和操作系统的功能,使得登录功能在移动设备上能够提供良好的用户体验。
社交登录和第三方登录:Spring Social 是一个用于与社交网络集成的框架,它提供了与微信、QQ、 - 微博等社交平台登录的功能。Spring Social 简化了与第三方身份提供者的集成过程。
单点登录和统一身份认证:Spring Security 支持单点登录(SSO)和联合身份验证(Federated Identity),这有助于减少用户在多个应用系统中重复登录的繁琐。Spring Cloud 中的 Spring Cloud OAuth2 提供了构建单点登录系统的解决方案。 - 法律法规和合规性:Spring 框架本身并没有直接解决法律法规和合规性问题的功能,但是它提供了一个灵活的开发框架,可以在其上构建符合法律法规和合规性要求的应用程序。例如,你可以利用 Spring 的 AOP(面向切面编程)特性来实现数据加密、日志记录和访问控制等功能。
可扩展性和灵活性:Spring 框架的核心是 IoC(控制反转)和 DI(依赖注入)容器,它允许开发者以松散耦合的方式构建应用程序。这种方式提供了极大的可扩展性和灵活性,使得登录功能可以方便地集成新的认证方式、支持多因素认证或与其他系统进行集成。
认证授权
拦截器实现session认证与授权
1.配置spring session
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session</artifactId>
</dependency>
- 配置session策略
spring.session.store-type=jdbc
spring.session.jdbc.table-name=spring_session
spring.session.jdbc.initialize-schema=embedded
- 登陆表单
<form action="/login" method="post">
<input type="text" name="username" placeholder="Username" required>
<input type="password" name="password" placeholder="Password" required>
<button type="submit">Login</button>
</form>
拦截器
5. 创建拦截器
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class AuthenticationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 检查Session中是否存在用户名,如果不存在,则重定向到登录页面
if (request.getSession().getAttribute("username") == null) {
response.sendRedirect("/login");
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 在请求处理之后执行的操作,这里可以添加一些日志记录或者其他处理逻辑
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 在整个请求完成后执行的操作,这里可以进行一些资源清理工作
}
}
- 注册拦截器
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthenticationInterceptor())
.addPathPatterns("/dashboard/**") // 保护需要认证的路径
.excludePathPatterns("/login", "/css/**", "/js/**"); // 排除不需要认证的路径
}
}
- 设置授权拦截器
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class AuthorizationInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 假设我们通过Session中的"role"属性来检查用户的角色
String role = (String) request.getSession().getAttribute("role");
if (role == null ||!role.equals("ADMIN")) {
// 用户没有ADMIN角色,重定向到拒绝访问页面或返回错误信息
response.sendRedirect("/access-denied");
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 在请求处理之后执行的操作,这里可以添加一些日志记录或者其他处理逻辑
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// 在整个请求完成后执行的操作,这里可以进行一些资源清理工作
}
}
- 注册拦截器
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthorizationInterceptor())
.addPathPatterns("/admin/**") // 保护需要ADMIN角色的路径
.excludePathPatterns("/login", "/css/**", "/js/**"); // 排除不需要认证的路径
}
}
- 登录和登出并授权
@Controller
public class LoginController {
@PostMapping("/login")
public String login(@RequestParam String username, @RequestParam String password, HttpSession session) {
// 这里应该进行实际的用户认证逻辑,例如检查数据库
// 假设用户名为"admin"的用户具有ADMIN角色
if ("admin".equals(username) && "test".equals(password)) {
// 认证成功,将用户名和角色存储在Session中
session.setAttribute("username", username);
session.setAttribute("role", "ADMIN");
return "redirect:/dashboard"; // 重定向到仪表板页面
} else {
// 认证失败,返回登录页面并显示错误消息
return "redirect:/login?error";
}
}
@GetMapping("/logout")
public String logout(HttpSession session) {
// 注销用户,移除Session中的用户名和角色
session.removeAttribute("username");
session.removeAttribute("role");
return "redirect:/login"; // 重定向到登录页面
}
}
- 设置session最大存活时间
server.servlet.session.timeout=30m
- 动态设置session存活时间
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.stereotype.Component;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
@Component
public class SessionTimeoutInitializer implements ServletContextInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
// 设置Session超时时间为60分钟
servletContext.setSessionTimeout(60 * 60);
}
}