【问题标题】:Spring basic authentication credentials from Javascript来自 Javascript 的 Spring 基本身份验证凭据
【发布时间】:2017-11-11 14:12:51
【问题描述】:

我们有一个应用程序使用 spring 基本身份验证来确保安全。该应用程序不是基于 Spring MVC 构建的。我们将聚合物用作前端,并将服务公开为基于休息的服务。

要求是实现一个登录表单,点击提交按钮需要调用一个应该发布用户名/密码的javascript。

有没有办法从 javascript 将凭据传递给 spring 基本身份验证 servlet,以便它验证请求。我们已经实现了 AuthenticationProvider 身份验证来执行验证。

认证java代码

import org.springframework.security.authentication.*;
import org.springframework.security.core.*;
import java.util.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.UriInfo;
import com.lifesciencemeta.ls.User;
import com.lifesciencemeta.ls.LifeScienceServiceMaster;
import com.lifesciencemeta.ls.LifeScienceConstants;

public class SpringBasicAuthentication implements AuthenticationProvider {
    public LifeScienceServiceMaster lifeScienceService;
    @Context
    UriInfo lsUri;
    public LifeScienceServiceMaster getLifeScienceService() {
        return lifeScienceService;
    }
    public void setLifeScienceService(LifeScienceServiceMaster lifeScienceService) {
        this.lifeScienceService = lifeScienceService;
    }
    @Override
    public Authentication authenticate(Authentication authentication)
            throws AuthenticationException {
        UsernamePasswordAuthenticationToken auth = (UsernamePasswordAuthenticationToken) authentication;
        String principal = (String) auth.getPrincipal();
        String credential = (String) auth.getCredentials();
        User u = lifeScienceService.authenticateUser(principal, credential);
        if (u == null)
            throw new BadCredentialsException(LifeScienceConstants.getMsg(“Auth Failed"));
        else {
            List<GrantedAuthority> grantedAuths = new ArrayList<GrantedAuthority>();
            String role = u.getRole().getName();
            if(role == null) {
                throw new BadCredentialsException(LifeScienceConstants.getMsg(“Auth Failed"));
            }
            grantedAuths.add(new SimpleGrantedAuthority(role));
            UsernamePasswordAuthenticationToken result = new UsernamePasswordAuthenticationToken(
                    principal, credential, grantedAuths);

            result.setDetails(u);
            return result;
        }

    }
    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);

    }

}

Web.xml

http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" 版本="2.5"> org.springframework.web.context.ContextLoaderListener 上下文配置位置 /WEB-INF/context.xml springSecurityFilterChain org.springframework.web.filter.DelegatingFilterProxy springSecurityFilterChain / 泽西 REST 服务 com.sun.jersey.spi.container.servlet.ServletContainer com.sun.jersey.config.property.packages com.lifesciencemeta.ls.restService.Invoke com.sun.jersey.api.json.POJOMappingFeature 真的 1 泽西 REST 服务 /休息/

安全性.xml

  <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:security="http://www.springframework.org/schema/security"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
               http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
               http://www.springframework.org/schema/security
               http://www.springframework.org/schema/security/spring-security-3.1.xsd">
        <security:global-method-security secured-annotations="enabled" jsr250-annotations="enabled" pre-post-annotations="enabled" />
        <security:http>
              <security:intercept-url   pattern="/**"  access="ROLE_USER, ROLE_ADMIN"/>
             <security:http-basic />
        </security:http>
        <security:authentication-manager alias="authenticationManager">
            <security:authentication-provider ref="SpringBasicAuthentication" />
        </security:authentication-manager> 
        <bean id="SpringBasicAuthentication" 
            class="com.lifesciencemeta.ls.SpringBasicAuthentication" >
            <property name="lifeScienceService" ref="lsLifeScienceServiceImpl"/>
        </bean>
    </beans>

【问题讨论】:

  • 所以您使用的是 Spring Security,对吗?此类任务的端点是 /login。
  • 感谢您的建议!

标签: javascript spring authentication


【解决方案1】:

您可以将 spring security 配置为使用基本身份验证,然后只需向任何受保护的资源以及带有基本身份验证信息的授权标头发送请求。

@SpringBootApplication
public class So44459836Application {

    public static void main(String[] args) {
        SpringApplication.run(So44459836Application.class, args);
    }

    @EnableWebSecurity
    public static class SecurityConfiguration extends WebSecurityConfigurerAdapter {
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/public/**"); //for static resources
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.formLogin().disable() //disable integrated login form 
                    .httpBasic().and() // we want http basic authentication
                    .authorizeRequests().anyRequest().authenticated(); // all requests are protected
        }
    }

    @RestController
    @RequestMapping("/api/me")
    public static class MeController {

        @GetMapping
        public String me(Principal principal) {
            return principal.getName(); // just return current username. 
        }
    }
}

示例表格

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>App</title>
</head>
<body>
<div>
    <section> <strong>Login</strong></section>

    <div>
        <label for="username">Username</label>
        <input type="text" id="username">
    </div>
    <div>
        <label for="password">Password</label>
        <input type="password" id="password">
    </div>

    <input type="button" onclick="login();" value="Authenticate">
</div>
</body>
<script type="text/javascript">
    'use strict';

    function login() {
        var username = document.getElementById('username').value;
        var password = document.getElementById('password').value;

        var  xhr = new XMLHttpRequest();
        xhr.open('GET', '/api/me', false, username, password);
        xhr.onload = function() {
            if (xhr.status === 200) {
                alert('User\'s name is ' + xhr.responseText);
            }
            else {
                alert('Request failed.  Returned status of ' + xhr.status);
            }
        };
        xhr.send();
    }
</script>
</html>

更新

对于旧版本的 spring-security JavaConfig 不可用,所以可以试试这个:

web.xml

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">

    <display-name>Spring3 App</display-name>

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <servlet>
        <servlet-name>spring-web</servlet-name>
        <servlet-class>
            org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>spring-web</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app>

spring-web-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <mvc:resources mapping="/public/**" location="/public/"/>
</beans>

applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:sec="http://www.springframework.org/schema/security"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security.xsd">

    <context:component-scan base-package="com.stackoverflow.so44459836"/>
    <mvc:annotation-driven/>

    <sec:http auto-config="true">
        <sec:intercept-url pattern="/api/**" access="IS_AUTHENTICATED_FULLY" />
        <sec:http-basic/>
    </sec:http>

    <sec:authentication-manager>
        <sec:authentication-provider>
            <sec:user-service>
                <sec:user name="admin" password="admin" authorities="ROLE_ADMIN"/>
            </sec:user-service>
        </sec:authentication-provider>
    </sec:authentication-manager>
</beans>

将上面示例中的示例控制器放置到组件扫描中指定的包中,并将 html 文件放置到 webapp/public 目录中,你应该会很好。

PS。我已经用spring-webmvc:3.1.4.RELEASEspring-security-{web,config}:3.1.7.RELEASE 尝试过这个示例。

【讨论】:

  • 谢谢你的建议,真的很有帮助!!
  • 我目前使用的是spring 3.1.4版本。有没有使用这个版本的解决方案。
  • 嗨,如果可能的话,请您分享您使用 spring-webmvc:3.1.4.RELEASE 和 spring-security-{web,config}:3.1.7.RELEASE 尝试过的示例项目。如果有 git 链接会很有帮助。
  • 我已经附上了我当前的代码,您能否建议需要进行更改以启用自定义登录。
  • 好吧,我不知道您为什么要尝试实现自己的AuthenticationProvider。更简单的方法是实现UserDetailsService,然后使用现有的 spring-secirity 基础设施。 UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); final Authentication authentication = authenticationManager.authenticate(authRequest); SecurityContext securityContext = SecurityContextHolder.getContext(); securityContext.setAuthentication(authentication);
猜你喜欢
  • 2020-12-03
  • 2012-08-30
  • 1970-01-01
  • 2013-03-19
  • 2011-11-12
  • 2020-02-24
  • 1970-01-01
  • 2012-09-03
  • 1970-01-01
相关资源
最近更新 更多