使用spring框架,ajax和JWT登录

时间:2015-08-27 21:34:01

标签: spring spring-mvc jwt

有一个需要用户身份验证的spring应用程序。

检查JWT cookie是否存在,然后允许用户访问,否则重定向到身份验证应用程序。

此身份验证应用程序根据数据库验证用户并使用JWT cookie(原始应用程序已知其私钥)作为url参数返回到原始应用程序。

原始应用程序然后设置JWT cookie,允许用户访问并向弹出后端发送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
    }
}

这是正确的做法吗?我应该直接在会话中设置值而不是使用spring组件吗?应该将jwt令牌存储在会话而不是cookie中吗?

2 个答案:

答案 0 :(得分:0)

为何使用Spring security

<强>配置:

在spring security configuration xml文件中使用security:form-login login-page标记。它会自动将您的应用程序重定向到登录页面。

REMEBER: 在您的控制器中配置这些网址(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>

这是关于春季安全的最佳reference tutorial,我遇到过。请尝试根据此配置您的应用程序,如果您想要两个配置( JAVA / XML ),请参阅MKYONG示例。

推荐:使用Spring安全性,它是一个很好的弹簧工具来操作/处理身份验证过程,它非常容易配置,你不必深入研究。

我希望这会有所帮助。

答案 1 :(得分:0)

首先,你必须考虑为什么要使用JWT。 创建JWT是为了参加特定的problems of modern web applications,主要是代表cookie的服务器状态问题。

  

<强> 1。应用程序分布在许多服务器上

     

今天的许多应用程序的部署方式与它们不同   过去。对于应用程序来说,它现在非常普遍 - 而且通常是必需的   分布在许多服务器上,以便增加正常运行时间   延迟问题得到缓解。这带来了副作用,   当用户访问应用程序时,不再保证   他们总是访问同一台服务器。   由于传统的身份验证依赖于服务器来保持   用户在内存中的身份验证状态,当应用程序崩溃时   从不同的服务器访问。用户可能登录了一个   服务器,但不包括应用程序分发的其他服务器   对面。

     

<强> 2。应用程序使用API​​进行数据

     

以这种方式使用API​​非常棒,但事情可能会变得具有挑战性   在身份验证方面。传统的使用方法   用户身份的会话和cookie在以下方面效果不佳   这些情况因为它们的使用将状态引入应用程序。一   RESTful API的原则是它应该是无状态的,意思是   当发出请求时,某些参数内的响应可以   总是可以预期没有副作用。用户的身份验证   国家引入了这样的副作用,打破了这一原则。   保持API无状态,因此没有副作用意味着   可维护性和调试变得更加容易。

     

第3。 CORS(在单页应用程序中很常见)

     

此处的另一个挑战是,提供API非常常见&gt;从一个服务器和实际应用程序从另一个服务器使用它。   为实现这一目标,我们需要启用跨源资源共享   (CORS)。由于cookie只能用于它们所在的域   起源于它们对不同域上的API的帮助不大   申请。

RESTful API每天都比较常见,必须为stateless by definition。 无状态功能允许horizontal scaling,因为任何服务器都可以访问请求。 您可以使用更简单的JSON API和无状态后端,并从没有REST的水平scalling中受益。 因此,如果您需要Custom JWT authentication that integrates with Spring之类的复杂授权,则可以使用method authorization并从授权部分中受益。

当你说

  

是否应将jwt令牌存储在会话而不是cookie中?

我认为你没有完全理解JWT,因为JWT令牌不必存储在服务器端(会话)中。这意味着服务器端的状态是JWT要避免的。 必须在针对登录端点(类似于/ login)的成功用户身份验证上创建JWT。这项工作将由注入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中并随每个请求发送。服务器将仅验证令牌的完整性,不再需要针对用户凭据的身份验证(除非令牌已过期)。

那么,您对JWT的期望是什么?哪些功能必须完成您的身份验证机制?