使用spring框架、ajax和JWT登录
Posted
技术标签:
【中文标题】使用spring框架、ajax和JWT登录【英文标题】:Login using spring framework, ajax and JWT 【发布时间】:2015-11-22 10:52:00 【问题描述】:有一个spring应用需要用户认证。
它检查 JWT cookie 是否存在,然后允许用户访问,否则重定向到身份验证应用程序。
此身份验证应用程序根据数据库验证用户并使用 JWT cookie(原始应用程序已知的私钥)作为 url 参数返回原始应用程序。
原始应用程序然后设置 JWT cookie,允许用户访问并向 Spring 后端发送 ajax 请求,从而重新初始化用户会话对象。
用户被定义为一个组件:
@Component
@Scope("session")
public class User
在控制器中,我这样做:
@Controller
@RequestMapping("/login")
@Scope("request")
public class LoginController
@Autowired
private User user;
@RequestMapping(value = "/do-login", method = RequestMethod.POST)
@ResponseBody
public String login(HttpServletRequest request) throws IOException
user = new User()
// SET USER PROPERTIES USING JWT TOKEN
这是正确的方法吗?我应该直接在会话中设置值而不是使用弹簧组件吗? jwt 令牌应该存储在会话中而不是 cookie 中吗?
【问题讨论】:
以我的方式,最好在spring框架中使用spring security进行用户认证。因为它比 JWT 更安全。如果您想采用这种方法,请回复,以便我可以为此发布一个很好的答案。 @AnkurMahajan 当然,这会很有帮助。 +1 用于使用 Spring-security。 Spring-security 不仅提供了登录功能,还提供了更多功能。 【参考方案1】:为什么要使用Spring security。
配置:
在你的 spring 安全配置 xml 文件中使用 security:form-login login-page
标签。它会自动将您的应用程序重定向到登录页面。
记住: 在你的控制器中配置这些 url(security:intercept-url pattern
)。
<security:http auto-config="true" use-expressions="true">
<security:intercept-url pattern="/login"
access="permitAll" />
<security:intercept-url pattern="/accessDenied"
access="permitAll" />
<security:intercept-url pattern="/loginFail"
access="permitAll" />
<security:intercept-url pattern="/logout"
access="permitAll" />
<security:intercept-url pattern="/resources/**"
access="permitAll" />
<security:intercept-url pattern="/**"
access="hasRole('ROLE_ADMIN')" />
<security:access-denied-handler
error-page="/accessDenied" />
<security:form-login login-page="/login"
default-target-url="/home" always-use-default-target="true"
authentication-failure-url="/loginFail" username-parameter="username"
password-parameter="password" />
<security:logout logout-success-url="/logout" />
</security:http>
这个是spring security上最好的reference tutorial,我遇到过。请尝试根据此配置您的应用程序,如果您想要两种配置(JAVA/XML)请参考MKYONG 示例。
推荐:使用 spring security,它是一个很棒的 spring 工具来操作/处理身份验证过程,而且它很容易配置,您不必深入了解。
我希望这会有所帮助。
【讨论】:
如果您想了解更多有关此答案的信息。留下评论吧,我会告诉你spring security配置xml中定义的每个安全属性。【参考方案2】:首先,你必须思考为什么要使用 JWT。 创建 JWT 是为了解决特定的 problems of modern web applications,主要是代表 cookie 的服务器状态问题。
1.应用分布在许多服务器上
今天的许多应用程序的部署方式与它们之前的方式不同 过去。现在,应用程序非常普遍——而且经常是必要的—— 分布在许多服务器上,从而增加正常运行时间 延迟问题得到缓解。随之而来的副作用是, 当用户访问应用程序时,不再保证 他们总是访问同一台服务器。 由于传统的身份验证依赖于服务器来保存 用户在内存中的身份验证状态,当应用程序发生故障时 从不同的服务器访问。用户可能登录了一个 服务器但不在应用程序分发的其他服务器上 跨越。
2。应用使用 API 获取数据
以这种方式使用 API 很棒,但事情可能会变得具有挑战性 当涉及到身份验证时。传统的使用方法 用于用户身份的会话和 cookie 在 这些情况是因为它们的使用将状态引入了应用程序。一 RESTful API 的原则之一是它应该是无状态的,这意味着 即,当发出请求时,某些参数内的响应可以 总是可以预期的,没有副作用。用户身份验证 state 引入了这样的副作用,打破了这个原则。 保持 API 无状态,因此没有副作用意味着 可维护性和调试变得更加容易。
3. CORS(在单页应用程序中很常见)
这里的另一个挑战是,从一台服务器提供 API 并让实际应用程序从另一台服务器使用它是很常见的。 为了实现这一点,我们需要启用跨域资源共享 (CORS)。由于 cookie 只能用于它们所在的域 起源,它们对不同域上的 API 的帮助并不大 应用程序。
RESTful API 越来越普遍,它们必须是 stateless by definition。 无状态功能允许horizontal scaling,因为任何服务器都可以处理请求。 您可以拥有一个带有无状态后端的更简单的 JSON API,并从没有 REST 的水平扩展中受益。 因此,如果您需要像method authorization 这样的复杂授权,您可以使用Custom JWT authentication that integrates with Spring 并从授权部分中受益。
当你说
jwt 令牌应该存储在 session 中而不是 cookie 中吗?
我认为您并没有完全理解 JWT,因为 JWT 令牌不必存储在服务器端(会话)中。这意味着服务器端的状态是 JWT 要避免的。 JWT 必须在针对登录端点(例如 /login)的成功用户身份验证时创建。这项工作将由注入到 UsernamePasswordAuthenticationFilter 的 AuthenticationSuccessHandler 完成。例如:
public class JWTAuthenticationSuccessHandler implements AuthenticationSuccessHandler
protected JWSSigner jwsSigner;
public JWTAuthenticationSuccessHandler(JWSSigner jwsSigner)
this.jwsSigner = jwsSigner;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException
String ipaddress = request.getRemoteAddr();
JWTClaimsSet.Builder builder = new JWTClaimsSet.Builder();
JWTClaimsSet claimsSet = builder.subject("subject").issuer("issuer").expirationTime(new Date(new Date().getTime() + 60 * 1000)).claim("ipaddress",ipaddress).build();
SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256), claimsSet);
try
signedJWT.sign(jwsSigner);
String serializedJWT = signedJWT.serialize();
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getOutputStream().println(serializedJWT);
catch (JOSEException e)
e.printStackTrace();// TODO
然后,客户端必须将令牌存储在localStorage or cookie 中,并随每个请求一起发送。服务器只会验证令牌的完整性,不再需要针对用户凭据的身份验证(除非令牌已过期)。
那么,您对智威汤逊的期望是什么?哪些功能必须完成您的身份验证机制?
【讨论】:
以上是关于使用spring框架、ajax和JWT登录的主要内容,如果未能解决你的问题,请参考以下文章
#私藏项目实操分享# Spring专题「开发实战」Spring Security与JWT实现权限管控以及登录认证指南
spring boot2整合shiro安全框架实现前后端分离的JWT token登录验证
Spring Security 构建基于 JWT 的登录认证