shiro+jwt如何实现单点登录

时间: 2023-03-13 18:30:45 浏览: 43
使用 Shiro JWT 实现单点登录可以分为以下几步: 1. 在服务端配置 Shiro JWT 过滤器,使其能够识别和验证 JWT 令牌。 2. 在用户登录时,服务端生成 JWT 令牌并返回给客户端。 3. 客户端在发起请求时,将 JWT 令牌放在 HTTP 头部的认证信息中,发送给服务端。 4. 服务端通过 Shiro JWT 过滤器验证 JWT 令牌的有效性。如果令牌有效,则允许用户访问;否则,拒绝用户访问。 5. 在服务端和客户端之间的所有请求中,都将带有 JWT 令牌,从而实现单点登录。
相关问题

shiro+jwt如何实现单点登录,代码实例

### 回答1: Shiro 支持使用 JSON Web Token (JWT) 实现单点登录 (SSO)。 实现步骤如下: 1. 在服务端生成 JWT 并返回给客户端。 2. 客户端保存 JWT 并在请求中加上 HTTP Header,如 "Authorization: Bearer JWT"。 3. 服务端收到请求后验证 JWT 的有效性。 4. 如果 JWT 有效,则允许访问请求的资源。 以下是一个使用 Shiro 实现 JWT 验证的示例代码: ```java 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.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; public class JwtRealm extends AuthorizingRealm { private String secretKey; public JwtRealm(String secretKey) { this.secretKey = secretKey; } @Override public boolean supports(AuthenticationToken token) { return token instanceof JwtToken; } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 这里可以根据 JWT 中的自定义字段来进行权限控制 return null; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { JwtToken jwtToken = (JwtToken) token; String jwt = jwtToken.getPrincipal().toString(); Claims claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody(); // 验证 JWT 是否过期 if (claims.getExpiration().before(new Date())) { throw new AuthenticationException("JWT 已过期"); } // 这里可以使用 claims 中的用户信息来创建 SimpleAuthenticationInfo 对象 return new SimpleAuthenticationInfo(jwt, jwt, "j ### 回答2: Shiro JWT是一种基于JSON Web Token(JWT)的认证方式,可以用于实现单点登录(Single Sign-On,SSO)。下面是一个简单的代码示例,展示如何使用Shiro JWT实现单点登录。 首先,需要添加Shiro和JWT的依赖包,可以使用Maven进行管理。在pom.xml文件中添加以下依赖项: ```xml <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.7.1</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.2</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.11.2</version> <scope>runtime</scope> </dependency> ``` 然后,需要创建一个JWT工具类,用于生成和解析JWT: ```java public class JWTUtil { private static final String SECRET_KEY = "your-secret-key"; private static final long EXPIRATION_TIME = 86400000; // 24 hours public static String createToken(String username) { Date now = new Date(); Date expirationDate = new Date(now.getTime() + EXPIRATION_TIME); return Jwts.builder() .setSubject(username) .setIssuedAt(now) .setExpiration(expirationDate) .signWith(SignatureAlgorithm.HS256, SECRET_KEY) .compact(); } public static String getUsernameFromToken(String token) { Claims claims = Jwts.parser() .setSigningKey(SECRET_KEY) .parseClaimsJws(token) .getBody(); return claims.getSubject(); } } ``` 接下来,在登录成功后生成JWT并返回给客户端: ```java public class LoginController { @PostMapping("/login") public String login(@RequestParam String username, @RequestParam String password) { // 验证用户名和密码 if (authenticateUser(username, password)) { // 生成JWT String token = JWTUtil.createToken(username); return token; } else { return "登录失败"; } } } ``` 在其他需要单点登录的接口中,可以使用Shiro的注解来验证JWT的有效性: ```java public class UserController { @RequiresAuthentication @GetMapping("/user/{id}") public String getUser(@PathVariable String id) { // 处理业务逻辑 return "User " + id; } } ``` 以上就是使用Shiro JWT实现单点登录的简单示例。在实际项目中,还需要结合数据库等存储方式来保存用户信息和JWT的校验过程,以及处理JWT过期等情况。 ### 回答3: 在Shiro中,实现JWT(JSON Web Token)的单点登录,需要以下步骤: 首先,确保已经集成了Shiro和JWT相关的依赖。 然后,定义一个Shiro的自定义Realm,用于验证用户身份和生成JWT。如下示例: ```java public class JWTRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 授权逻辑,可根据具体需求进行自定义实现 return null; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { JWTToken jwtToken = (JWTToken) token; String jwt = jwtToken.getToken(); // 解析JWT并验证用户身份 String username = JWTUtils.getUsername(jwt); String password = JWTUtils.getPassword(jwt); // 根据用户名查询数据库或其他存储,获取用户信息 // 此处省略数据库查询逻辑 if (username == null || !password.equals("123456")) { throw new IncorrectCredentialsException("用户身份验证失败"); } // 用户身份验证通过,返回AuthenticationInfo对象 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username, jwt, getName()); return authenticationInfo; } @Override public boolean supports(AuthenticationToken token) { return token instanceof JWTToken; } } ``` 接下来,配置Shiro的过滤链,让Shiro对请求进行JWT认证和授权的处理。如下示例: ```java public class ShiroConfig { @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager); shiroFilterFactoryBean.setLoginUrl("/login"); shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized"); // 添加自定义的JWT过滤器 Map<String, Filter> filters = new HashMap<>(); filters.put("jwt", new JWTFilter()); shiroFilterFactoryBean.setFilters(filters); // 配置过滤链 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>(); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/**", "jwt"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); return shiroFilterFactoryBean; } @Bean public DefaultWebSecurityManager securityManager(ShiroRealm shiroRealm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(shiroRealm); return securityManager; } @Bean public ShiroRealm shiroRealm() { return new ShiroRealm(); } } ``` 最后,创建一个JWT过滤器,用于处理JWT的验证和登录。如下示例: ```java public class JWTFilter extends AuthenticatingFilter { @Override protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) { String jwt = getTokenFromRequest(request); if (StringUtils.isNotBlank(jwt) && JWTUtils.verifyToken(jwt)) { return new JWTToken(jwt); } return null; } @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { redirectToLogin(request, response); return false; } @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) { if (isLoginAttempt(request, response)) { try { executeLogin(request, response); } catch (Exception e) { e.printStackTrace(); } } return true; } private boolean isLoginAttempt(ServletRequest request, ServletResponse response) { String jwt = getTokenFromRequest(request); return StringUtils.isNotBlank(jwt) && JWTUtils.verifyToken(jwt); } private String getTokenFromRequest(ServletRequest request) { HttpServletRequest httpServletRequest = (HttpServletRequest) request; String jwt = httpServletRequest.getHeader("Authorization"); if (StringUtils.isNotBlank(jwt) && jwt.startsWith("Bearer ")) { return jwt.replace("Bearer ", ""); } return null; } private void redirectToLogin(ServletRequest request, ServletResponse response) { HttpServletResponse httpServletResponse = (HttpServletResponse) response; httpServletResponse.setStatus(HttpStatus.UNAUTHORIZED.value()); } } ``` 这样就实现了使用Shiro和JWT实现单点登录的功能。使用以上代码示例,可根据具体需求进行扩展和自定义。

Jwt redis shiro实现单点登录

单点登录是指用户只需要登录一次即可访问多个应用系统,而不需要针对每个应用系统单独登录。实现单点登录的方案很多,其中使用JWT、Redis和Shiro的组合可以实现一个轻量的、安全的单点登录方案。 具体实现步骤如下: 1. 首先,用户在登录系统时输入账号和密码提交登录请求。后端系统验证通过后,生成一个JWT Token,并将Token保存到Redis缓存中。 2. 把JWT Token返回给前端界面,前端将Token保存在浏览器的Cookie中。 3. 当用户访问第二个应用系统时,前端将Cookie中的Token发送到后端进行验证。后端系统从Redis缓存中获取Token,验证通过后返回结果,用户即可访问该应用系统。 4. 在验证过程中,使用Shiro进行权限控制,保障系统安全。 使用JWT、Redis和Shiro实现单点登录的好处是: 1. JWT Token在客户端和服务端之间传输时是加密的,保证了系统的安全性。 2. Redis缓存可以实现分布式缓存,提高系统性能。 3. Shiro封装了常见的安全操作,使用起来简单方便。 综上所述,使用JWT、Redis和Shiro实现单点登录是一种轻量、安全、高效的方案,可以大大提高用户体验和系统安全性。

相关推荐

最新推荐

recommend-type

基于JWT实现SSO单点登录流程图解

基于JWT实现SSO单点登录流程图解 基于JWT实现SSO单点登录流程图解是指使用JSON Web Token(JWT)来实现单点登录(SSO)的机制。在这种机制中,用户只需要登录一次,就可以访问多个应用服务器上的资源,而不需要再次...
recommend-type

服务器虚拟化部署方案.doc

服务器、电脑、
recommend-type

北京市东城区人民法院服务器项目.doc

服务器、电脑、
recommend-type

求集合数据的均方差iction-mast开发笔记

求集合数据的均方差
recommend-type

Wom6.3Wom6.3Wom6.3

Wom6.3Wom6.3Wom6.3
recommend-type

VMP技术解析:Handle块优化与壳模板初始化

"这篇学习笔记主要探讨了VMP(Virtual Machine Protect,虚拟机保护)技术在Handle块优化和壳模板初始化方面的应用。作者参考了看雪论坛上的多个资源,包括关于VMP还原、汇编指令的OpCode快速入门以及X86指令编码内幕的相关文章,深入理解VMP的工作原理和技巧。" 在VMP技术中,Handle块是虚拟机执行的关键部分,它包含了用于执行被保护程序的指令序列。在本篇笔记中,作者详细介绍了Handle块的优化过程,包括如何删除不使用的代码段以及如何通过指令变形和等价替换来提高壳模板的安全性。例如,常见的指令优化可能将`jmp`指令替换为`push+retn`或者`lea+jmp`,或者将`lodsbyteptrds:[esi]`优化为`moval,[esi]+addesi,1`等,这些变换旨在混淆原始代码,增加反逆向工程的难度。 在壳模板初始化阶段,作者提到了1.10和1.21两个版本的区别,其中1.21版本增加了`Encodingofap-code`保护,增强了加密效果。在未加密时,代码可能呈现出特定的模式,而加密后,这些模式会被混淆,使分析更加困难。 笔记中还提到,VMP会使用一个名为`ESIResults`的数组来标记Handle块中的指令是否被使用,值为0表示未使用,1表示使用。这为删除不必要的代码提供了依据。此外,通过循环遍历特定的Handle块,并依据某种规律(如`v227&0xFFFFFF00==0xFACE0000`)进行匹配,可以找到需要处理的指令,如`push0xFACE0002`和`movedi,0xFACE0003`,然后将其替换为安全的重定位值或虚拟机上下文。 在结构体使用方面,笔记指出壳模板和用户代码都会通过`Vmp_AllDisassembly`函数进行解析,而且0x8和0x10字段通常都指向相同的结构体。作者还提到了根据`pNtHeader_OptionalHeader.Magic`筛选`ESI_Matching_Array`数组的步骤,这可能是为了进一步确定虚拟机上下文的设置。 这篇笔记深入解析了VMP技术在代码保护中的应用,涉及汇编指令的优化、Handle块的处理以及壳模板的初始化,对于理解反逆向工程技术以及软件保护策略有着重要的参考价值。
recommend-type

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire
recommend-type

【进阶】音频处理基础:使用Librosa

![【进阶】音频处理基础:使用Librosa](https://picx.zhimg.com/80/v2-a39e5c9bff1d920097341591ca8a2dfe_1440w.webp?source=1def8aca) # 2.1 Librosa库的安装和导入 Librosa库是一个用于音频处理的Python库。要安装Librosa库,请在命令行中输入以下命令: ``` pip install librosa ``` 安装完成后,可以通过以下方式导入Librosa库: ```python import librosa ``` 导入Librosa库后,就可以使用其提供的各种函数
recommend-type

python中字典转换成json

在Python中,你可以使用`json`模块将字典转换为JSON格式的字符串。下面是一个简单的示例: ```python import json # 假设我们有一个字典 dict_data = { "name": "John", "age": 30, "city": "New York" } # 使用json.dumps()函数将字典转换为JSON json_string = json.dumps(dict_data) print(json_string) # 输出:{"name": "John", "age": 30, "city": "New York"}
recommend-type

C++ Primer 第四版更新:现代编程风格与标准库

"Cpp Primer第四版中文版(电子版)1" 本书《Cpp Primer》第四版是一本深入浅出介绍C++编程语言的教程,旨在帮助初学者和有经验的程序员掌握现代C++编程技巧。作者在这一版中进行了重大更新,以适应C++语言的发展趋势,特别是强调使用标准库来提高编程效率。书中不再过于关注底层编程技术,而是将重点放在了标准库的运用上。 第四版的主要改动包括: 1. 内容重组:为了反映现代C++编程的最佳实践,书中对语言主题的顺序进行了调整,使得学习路径更加顺畅。 2. 添加辅助学习工具:每章增设了“小结”和“术语”部分,帮助读者回顾和巩固关键概念。此外,重要术语以黑体突出,已熟悉的术语以楷体呈现,以便读者识别。 3. 特殊标注:用特定版式标注关键信息,提醒读者注意语言特性,避免常见错误,强调良好编程习惯,同时提供通用的使用技巧。 4. 前后交叉引用:增加引用以帮助读者理解概念之间的联系。 5. 额外讨论和解释:针对复杂概念和初学者常遇到的问题,进行深入解析。 6. 大量示例:提供丰富的代码示例,所有源代码都可以在线获取,便于读者实践和学习。 本书保留了前几版的核心特色,即以实例教学,通过解释和展示语言特性来帮助读者掌握C++。作者的目标是创作一本清晰、全面、准确的教程,让读者在编写程序的过程中学习C++,同时也展示了如何有效地利用这门语言。 《Cpp Primer》第四版不仅适合C++初学者,也适合想要更新C++知识的老手,它全面覆盖了C++语言的各个方面,包括基础语法、类、模板、STL(Standard Template Library)等,同时引入了现代C++的特性,如智能指针、RAII(Resource Acquisition Is Initialization)、lambda表达式等,使读者能够跟上C++语言的发展步伐,提升编程技能。