如何使用 Spring Security 和 Angularjs 保护 Spring Rest 服务?

Posted

技术标签:

【中文标题】如何使用 Spring Security 和 Angularjs 保护 Spring Rest 服务?【英文标题】:How to Secure Spring Rest Services with Spring Sercurity and Angularjs? 【发布时间】:2014-04-13 22:19:28 【问题描述】:

我有一个带有 Rest-Services 和 AngularJS WebFrontend 的 Spring MVC 服务器后端。

我想保护我的 spring mvc 休息服务,但我想使用 java config.. 我不知道配置应该是什么样子。有人可以帮我弄这个吗 ? 我发现的唯一好的实现是:https://github.com/philipsorst/angular-rest-springsecurity

我使用 postgrsDB,我想在那里存储用户名和密码以及角色,https://github.com/philipsorst/angular-rest-springsecurity 示例中的会话令牌是否仅存储在缓存中而不是数据库中?

目前我有一个简单的表单登录安全性,这仅用于测试,但我没有使用 jsp 我只使用 spring mvc 休息服务和 angularjs 作为 webfrontend.. 我如何修改我的 spring 安全代码它像 https://github.com/philipsorst/angular-rest-springsecurity 的示例中那样与 oauth2 一起使用?我目前只有这两个来自 spring security 的课程..

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception 

        auth
        .inMemoryAuthentication()
        .withUser("username").password("test").roles("User");
    

然后我在我的 WebInitializer 中注册 securityConfig。

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer 

@Override
protected Class<?>[] getRootConfigClasses() 
    return new Class<?>[] PersistenceContext.class,AppConfig.class,SecurityConfig.class ; 
 ....

但是角色和用户名/密码应该存储在数据库中。我必须使用特殊的数据库模式来实现 spring 安全性来在我的数据库中存储用户名、密码和角色吗?

我可以实现它,以便我只能在其中一个角色的其余服务上添加@Secured Annotation(或任何其他注释)吗?喜欢@Secured("UserRole")

还是更简单的基本认证?我可以通过角色管理的基本身份验证来保护我的休息服务!?如果是这样,我们可以使用基本身份验证.. 最好的问候

【问题讨论】:

【参考方案1】:

为了加载用户,您必须创建一个身份验证管理器并将 UserDetailsS​​ervice 连接到该身份验证管理器。以下文档链接很好地概述了身份验证管理器以及相关的核心组件。

http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#core-services

所以,回答你的第一个问题……

但是角色和用户名/密码应该存储在数据库中.. 我必须使用特殊的 用于 Spring Security 的数据库模式,用于在我的数据库中存储用户名、密码和角色?

你可以做任何一个。如果您愿意,spring security 可以为您处理所有数据库端,您只需提供对具有 Spring 架构设计的 JDBC 数据源的引用。

http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#core-services-jdbc-user-service

http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/#appendix-schema

-或-

您可以通过提供您自己的 UserDetailsS​​ervice 实现来利用您自己的架构,该实现将从您自己的数据库架构中加载。这里有一些示例可以帮助您开始使用这种方法。

<context:component-scan base-package="com.example.security" />
<security:global-method-security secured-annotations="enabled" pre-post-annotations="enabled"/>

<bean id="dao-provider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"
      p:userDetailsService-ref="myUserDetailsService"
      p:passwordEncoder-ref="sha-pw-encoder"
      p:saltSource-ref="my-salt-source" />

<bean id="sha-pw-encoder" class="org.springframework.security.authentication.encoding.ShaPasswordEncoder"
      p:encodeHashAsBase64="true" />

<bean id="my-salt-source" class="org.springframework.security.authentication.dao.ReflectionSaltSource"
      p:userPropertyToUse="salt" />

<security:authentication-manager>
    <security:authentication-provider ref="dao-provider"/>
</security:authentication-manager>

最后,像这样提供 UserDetailsS​​ervice 的实现:

@Component("myUserDetailsService")
public class MyUserDetailsServiceImpl implements UserDetailsService 

//Reference to the spring JPA repository for loading users
private final UserRepository userRepository;

@Autowired
public MyUserDetailsServiceImpl(UserRepository userRepository) 
    this.userRepository = userRepository;


@Override
@Transactional
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException         
    User user = userRepository.findByName(username);
    if (user != null) 
        return new UserDetails() 
          ... //create the user details from the user object
        
     else 
        String err = String.format("Failed to find username: %s in local database.  Trying other auth mechanisms.", username);
        throw new UsernameNotFoundException(err);
    
  

...关于你的第二个问题:

我可以实现它,以便我只能添加@Secured Annotation(或任何其他 注释)在我的其余服务中扮演角色之一吗?喜欢@Secured("UserRole")

是的,以上配置将允许您通过配置 global-method-security 来使用@Secured 注解。

最后,是的,所有这些默认情况下仍将使用基本身份验证,但如有必要,可以重新配置为使用摘要身份验证。我建议完整阅读http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/ 的文档,以便真正掌握您想要做什么。但是,这应该会让你上路。

【讨论】:

嗯,我的项目中没有使用 JPA,也没有 xml 文件。安全模式不太好我不希望用户名作为主键我想要一个普通的 ID 作为整数,然后是用户名密码。 Hoq 我可以将上面的 xml 转换为 java 吗? 我使用 Jooq 作为我的数据库映射层jooq.org 并且没有 JPA 或 DAO,但 jooq 可以生成 DAOS 但我不知道这是否适用于 spring.. 我可以在没有 JPA 的情况下进行用户服务吗?我该如何转换:“bean id="dao-provider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider" p:userDetailsS​​ervice-ref="myUserDetailsS​​ervice" p:passwordEncoder-ref="sha-pw-编码器" p:saltSource-ref="my-salt-source" />" 到我没有 JPA 的 Jooq 实现? 对不起,我不知何故错过了你一开始在做 Java 配置......所以,你应该能够做到以下几点: 1) 按照我上面的建议创建 UserDetailsS​​ervice 实现。 2) 代替 auth.inMemoryAuthentication() 调用 auth.userDetailsS​​ervice(myUserDetailsS​​ervice),传入您自己的用户详细信息服务参考。 3)您可以让您的 UserDetailsS​​ervice 使用您想要加载用户名的任何方法,是否使用 jooq 应该是无关紧要的,只要您可以加载用户对象,然后将您的用户格式转换为 UserDetails 对象,这就是是必需的。 你能做一个这样的 UserDetails 对象的例子吗?我有 2 个表,其中一个是具有 id(作为主键)、用户名、密码和 role_ID 作为外键的帐户。第二个表是roles_lookup,其中role_id 作为主键和rolename。在表中role_lookup 是role_id 1 =“admin”和role_id 2 =“user”。 Account Table 中的 Foreignt Key 链接到 roles_lookup 表。我可以将此 Tabes 用于 userdetailsservice 吗?如何使用 jdbc 和我的表创建用户对象?

以上是关于如何使用 Spring Security 和 Angularjs 保护 Spring Rest 服务?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Spring-Security 3 和 Hibernate 4 将 spring security xml 配置 hibernate 转换为 java config

如何使用spring-security通过用户名和密码登录?

spring-security 开启注解权限控制为什么没有效果

如何使用 spring-security 和 jQuery 处理过期会话?

spring security 配置了httpBasic()为啥没有弹框

如何使用 Spring Security 和 Angularjs 保护 Spring Rest 服务?