2016-05-12 79 views
0

我知道这是n。关于Spring Security的文章,我读了很多,直到我决定发布我的问题,因为 - 我认为 - 由于Spring Boot的本质,必须在引擎盖下面隐藏一些问题,这是特定于我正在使用的Boot版本/安全类型的星座。Spring Boot 1.3.3。,Spring Security基本自定义配置

让我进入它。

的pom.xml:

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-data-jpa</artifactId> 
</dependency> 

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-jersey</artifactId> 
</dependency> 

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-web</artifactId> 
</dependency> 

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-security</artifactId> 
    <version>1.2.5.RELEASE</version> 
</dependency> 

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-test</artifactId> 
    <scope>test</scope> 
</dependency> 

我的基本安全配置:

@Configuration 
@EnableWebSecurity 
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private UserDetailsService userDetailsService; 

    @Autowired 
    private StudentRepository studentRepository; 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 

    http.csrf().disable() 
     .authorizeRequests() 
      .antMatchers("/").access("hasRole('ROLE_STUDENT')") 
      .antMatchers("/**").permitAll(); 
     .and() 
      .formLogin() 
      .loginPage("/login") 
      .failureUrl("/login?error=true"); 
    } 

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth 
     .userDetailsService(new UserDetailsService() { 
      @Override 
      public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 
       Iterable<Student> studentsWithIds = studentRepository.findAll(); 

       for (Student student: studentsWithIds) { 
        if (student.getName() == username) { 
         return studentRepository.findOne(student.getId()); 
        } 
       } 
        throw new UsernameNotFoundException("User '" + username + "' not found."); 
      } 
     });  
    } 
} 

我Student类实现的UserDetails(与简单起见角色硬连线凭证是ROLE_STUDENT):

@Entity 
public class Student implements UserDetails { 

    @Id @GeneratedValue(strategy=GenerationType.AUTO) 
    private Integer id; 

    @Column(unique=true) 
    private Integer facebookId; 

    @Column(unique=true) 
    private Integer googleId; 

    private String name = ""; 
    private String password = ""; 


    public void setName(String name) { 
     this.name = name; 
    } 


    public String getName() { 
     return this.name; 
    } 

    public String getPassword() { 
     return this.password; 
    } 

    public void initialize(String studentName) { 
     this.name = "student1"; 
     this.password = "password"; 
    } 

    @Override 
    public String toString(){ 
     return "Student with name " + name + "id: " + id; 
    } 

    public Integer getId() { 
     return id; 
    } 

    @Override 
    public Collection<? extends GrantedAuthority> getAuthorities() { 
     return Arrays.asList(new SimpleGrantedAuthority("ROLE_STUDENT")); 
    } 

    @Override 
    public String getUsername() { 
     return this.name; 
    } 

    @Override 
    public boolean isAccountNonExpired() { 
     // TODO Auto-generated method stub 
     return true; 
    } 

    @Override 
    public boolean isAccountNonLocked() { 
     // TODO Auto-generated method stub 
     return true; 
    } 

    @Override 
    public boolean isCredentialsNonExpired() { 
     // TODO Auto-generated method stub 
     return true; 
    } 

    @Override 
    public boolean isEnabled() { 
     // TODO Auto-generated method stub 
     return true; 
    } 

} 

就是这样。我没有任何其他安全相关的配置或注释,并且据我所知我不需要其他任何东西。

问题是,当我启动应用程序时,我仍然无法使用“student1”/“password”进行身份验证,但仅使用默认的“user”/。

任何想法什么是缺少请吗?谢谢!

Naturally there is a user already in the database 后调试模式中接通:

22:06:54.067 [HTTP-NIO-8280-EXEC-1] DEBUG osswaAnonymousAuthenticationFilter - 填充的SecurityContextHolder中与匿名的令牌:“org.springframework.security .authentication.AnonymousAuthenticationToken @ 9055c2bc:主体:anonymousUser;证书:[PROTECTED];已验证:true;详细信息:org.sprin[email protected]b364:RemoteIpAddress:0:0:0:0:0:0:0:1; SessionId:null;授予权限:ROLE_ANONYMOUS' 22:06:54.067 [http-nio-8280-exec-1] DEBUG org.springframework.security.web.FilterChainProxy -/students/1位于11的9位,位于附加的过滤器链中;其他过滤器链中的位置10处的/ students/1调用过滤器:'SessionManagementFilter' 22:06:54.067 [http-nio-8280-exec-1] DEBUG org.springframework.security.web.FilterChainProxy - “FilterTranslationFilter” 22:06:54.067 [http-nio-8280-exec-1] DEBUG org.springframework.security.web.FilterChainProxy -/students/1在另一个过滤器链中的位置11; “FilterSecurityInterceptor' 22:06:54.068 [http-nio-8280-exec-1] DEBUG o.s.s.wap.intercept.FilterSecurityInterceptor - Secure object:FilterInvocation:URL:/ students/1;属性:[hasAnyRole('ROLE_USER')] 22:06:54.068 [http-nio-8280-exec-1] DEBUG osswaccess.intercept.FilterSecurityInterceptor - 先前已通过身份验证:org.sprin[email protected]9055c2bc:校长:anonymousUser;证书:[PROTECTED];已验证:true;详细信息:org.sprin[email protected]b364:RemoteIpAddress:0:0:0:0:0:0:0:1; SessionId:null;授予权限:ROLE_ANONYMOUS 22:06:54.072 [http-nio-8280-exec-1] DEBUG ossecurity.access.vote.AffirmativeBased - Voter:org.sp[email protected]272de199,returned :-1 22:06:54.072 [http-nio-8280-exec-1] DEBUG osbfactory.support.DefaultListableBeanFactory - 返回单例bean的缓存实例'delegatingApplicationListener' 22:06:54.073 [http-nio-8280- exec-1] DEBUG ossecurity.web.access。ExceptionTranslationFilter - 访问被拒绝(用户是匿名的);重定向到身份验证入口点 org.springframework.security.access.AccessDeniedException:访问是在org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:83) 在org.springframework.security.access否认 .intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:232) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:123) at org.springframework.security.web.access.intercept .FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:90) at org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:330) at org.springframework.security.web.access.ExceptionTranslationFilter.doF ilter(ExceptionTranslationFilter.java:114) at org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:330) at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java: 122) 在org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:330) 在org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111) 在有机springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:330) at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169) at org.springfr amework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:330) at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:48) at org.springframework.security.web。的FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:330) 在org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilterInternal(BasicAuthenticationFilter.java:158) 在org.springframework.web.filter.OncePerRequestFilter.doFilter( OncePerRequestFilter.java:107) at org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:330) at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java: 120) at org.spring framework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:330) at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64) at org.springframework.web.filter。 OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 在org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:330) 在org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter。 java:91) at org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:330) at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java: 53) 在org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 在org.springframework.security.web.FilterChainProxy $ VirtualFilterChain.doFilter(FilterChainProxy.java:330) 在org.springframework.security。 web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:213) 在org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:176) 在org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java: 346) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain。的java:240) 在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 在org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) 在org.springframework。 web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain。的java:207) 在org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87) 在org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 在org.apache。 catalina.core.Applicati onFilterChain.internalDoFilter(ApplicationFilterChain.java:240) 在org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 在org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) 在org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) 在org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) 在org.apache.catalina.core。 ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) 在org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:121) 在org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207) at org.apache.catalina.core。 StandardWrapperValve.invoke(StandardWrapperValve.java:212) 在org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) 在org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) 在org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141) 在org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) 在org.apache.catalina.core。 StandardEngineValve.invoke(StandardEngineValve.java:88) at org.apache .catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095) at org.apache.coyote.AbstractProtocol $ AbstractConnectionHandler.process(AbstractProtocol .java:672) at org.apache.tomcat.util.net.NioEndpoint $ SocketProcessor.doRun(NioEndpoint.java:1500) at org.apache.tomcat.util.net.NioEndpoint $ SocketProcessor.run(NioEndpoint.java (未知源) at org.apache.tomcat.util.threads.TaskThread $ WrappingRunnable(未知源) .run(TaskThread.java:61) at java.lang.Thread.run(Unknown Source) 22:06:5 4.073 [http-nio-8280-exec-1] DEBUG o.s.security.web.access.ExceptionTranslationFilter - 调用身份验证入口点。 22:06:54.073 [http-nio-8280-exec-1] DEBUG ossweb.context.SecurityContextPersistenceFilter - SecurityContextHolder现在被清除,因为请求处理已完成 22:06:54.073 [http-nio-8280-exec-1] DEBUG osboot.context.web.OrderedRequestContextFilter - 清除线程绑定的请求上下文:[email protected] 22:06:54.077 [http-nio-8280-exec-1] DEBUG org.springframework。 web.servlet.DispatcherServlet - 名为'dispatcherServlet'的DispatcherServlet处理[/ error]的GET请求 22:06:54.080 [http-nio-8280-exec-1] DEBUG oswsmmaRequestMappingHandlerMapping - 查找路径/错误的处理方法 22:06:54.083 [http-nio-8280-exec-1] DEBUG oswsmmaRequestMappingHandlerMapping - 返回处理程序方法[public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)] 22: 06:54.083 [http-nio-8280-exec-1] DEBUG osbfactory.support.DefaultListableBeanFactory - 返回单例bean的缓存实例'basicErrorController' 22:06:54.084 [http-nio-8280-exec-1] DEBUG org .springframework.web.servlet.DispatcherServlet - [/ error]的Last-Modified值为:-1 22:06:54.084 [http-nio-8280-exec-1] DEBUG osojsupport.OpenEntityManagerInViewInterceptor - 在OpenEntityManagerInViewInterceptor中打开JPA EntityManager 22:06:54.104 [http-nio-8280-exec-1] DEBUG oswservlet.view.ContentNegotiatingViewResolver - 请求的媒体类型为[text/html,text/html; q = 0.8]接受标题类型和可生成的媒体类型[text/html]) 22:06:54.104 [http-nio-8280-exec-1] DEBUG osbfactory.support.DefaultListableBeanFactory - 返回单例bean的缓存实例'error' 22: 06:54.107 [http-nio-8280-exec-1] DEBUG osbfactory.support.DefaultListableBeanFactory - 在名为'error'的bean上调用afterPropertiesSet() 22:06:54.107 [http-nio-8280-exec-1] DEBUG oswservlet.view.ContentNegotiatingViewResolver - 基于请求的媒体类型'text/html'返回[org.springfram[email protected]2fb1fefe] 22:06:54.107 [http-nio-8280-exec -1] DEBUG org.springframework.web.servlet.DispatcherServlet - 在名为'dispatcherServlet'的DispatcherServlet中的渲染视图[org.springfram[email protected]2fb1fefe] 2 2:06:54.113 [http-nio-8280-exec-1] DEBUG osojsupport.OpenEntityManagerInViewInterceptor - 关闭OpenEntityManagerInViewInterceptor中的JPA EntityManager 22:06:54.113 [http-nio-8280-exec-1] DEBUG osorm.jpa。 EntityManagerFactoryUtils - 关闭JPA EntityManager 22:06:54.113 [http-nio-8280-exec-1] DEBUG org.springframework.web.servlet.DispatcherServlet - 成功完成请求 22:06:54.114 [http-nio-8280-exec -1] DEBUG osbfactory.support.DefaultListableBeanFactory - 返回单例bean的缓存实例'delegatingApplicationListener' 22:07:02.728 [http-nio-8280-exec-2] DEBUG调试osboot.context.web.OrderedRequestContextFilter - 绑定的请求上下文to thread:[email protected] 22:07:02.728 [http-nio-8280-exec-2] DEBUG ossweb.util.matcher.AntPathRequestMatcher - 检查垫请求的次数:'/ students/1'; '/ css/' 22:07:02.728 [http-nio-8280-exec-2] DEBUG o.s.s.web.util.matcher.AntPathRequestMatcher - 检查请求匹配:'/ students/1'; '/ js/' 22:07:02.728 [http-nio-8280-exec-2] DEBUG o.s.s.web.util.matcher.AntPathRequestMatcher - 检查请求匹配:'/ students/1'; '/ images/' 22:07:02.728 [http-nio-8280-exec-2] DEBUG o.s.s.web.util.matcher.AntPathRequestMatcher - 检查请求匹配:'/ students/1';反对'/ /favicon.ico' 22:07:02.728 [http-nio-8280-exec-2] DEBUG o.s.s.web.util.matcher.AntPathRequestMatcher - 检查请求匹配:'/ students/1'; 'error' 22:07:02.728 [http-nio-8280-exec-2] DEBUG ossecurity.web.util.matcher.OrRequestMatcher - 尝试使用Ant匹配[pattern ='/ '] 22: 07:02.728 [http-nio-8280-exec-2] DEBUG ossweb.util.matcher.AntPathRequestMatcher - 请求'/ students/1'通用模式'/' 22:07:02.728 [http-nio- 8280-exec-2]调试ossecurity.web.util.matcher.OrRequestMatcher - 匹配 22:07:02.728 [http-nio-8280-exec-2] DEBUG org.springframework.security.web.FilterChainProxy -/students/1在另外的滤波器链中的11位置1;在过滤器链中的11位置2处调用org.springframework.security.web.FilterChainProxy -/students/1;发射过滤器:'SecurityContextPersistenceFilter' 22:07:02.728 [http-nio-8280-exec-2] DEBUG org.springframework。security.web.FilterChainProxy -/students/1位于11的第3位,位于附加的过滤器链中; “HeaderWriterFilter” 22:07:02.728 [http-nio-8280-exec-2] DEBUG ossecurity.web.header.writers.HstsHeaderWriter - 由于它与requestMatcher org.springframework不匹配,不注入HSTS头。 security.web[email protected] 22:07:02.728 [http-nio-8280-exec-2] DEBUG org.springframework.security.web.FilterChainProxy -/students/1在11的位置4在额外的过滤器链中;点击过滤器:'LogoutFilter' 22:07:02.728 [http-nio-8280-exec-2] DEBUG o.s.s.web.util.matcher.AntPathRequestMatcher - 检查请求匹配:'/ students/1';反对'/注销' 22:07:02.728 [http-nio-8280-exec-2] DEBUG org.springframework.security.web.FilterChainProxy -/students/1启动Filter:'BasicAuthenticationFilter' 22:07:02.730 [http-nio-8280-exec-2] DEBUG osswawww.BasicAuthenticationFilter - 为用户'student1'找到的基本身份验证授权标头 22:07:02.730 [http-nio- 8280-exec-2]调试ossecurity.authentication.ProviderManager - 使用org.springframework.security.authentication.dao.DaoAuthenticationProvider进行身份验证尝试 22:07:02.731 [http-nio-8280-exec-2] DEBUG ossauthentication.dao .DaoAuthenticationProvider - 用户“student1”未找到

尽头似乎是最有趣的,虽然其余的是很丑陋太:

ossauthentication.dao.DaoAuthenticationProvider - 用户“student1” 没有找到

这里就是我呼吁学生在初始化(它的欺骗,因为它应该在POST被调用,但同样,我只是骗将学生放在数据库中,并将其用于认证。稍后会有明显的不同。 当然,我只能让这个GET当我temporarely停用上的应用程序)安全性:

@RequestMapping(value="/students", method=RequestMethod.GET, produces=MediaType.APPLICATION_JSON_UTF8_VALUE) 
public ResponseEntity<Iterable<Student>> listStudents() { 
    LOGGER.info("/students controller method call"+new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date())); 
    Iterable<Student> studentsFound = studentRepository.findAll(); 

    Student newStudent = new Student(); 
    newStudent.initialize("student1"); 
    studentRepository.save(newStudent); 

    return new ResponseEntity<Iterable<Student>>(studentsFound, HttpStatus.OK);   
} 

你觉得学生实例本身是某种不正确的?

+0

你在哪里调用'Student'的'initialize'方法? –

+0

添加了初始化部分。扩展了一些解释(我知道它在那里没有意义,但只是想把一个学生保存到数据库中,无论哪个部分都已经工作,所以我已经把它放在那里了.DB处于更新模式,该记录当然仍然在数据库中,但我也仔细检查了它) – Andrel

回答

2

的问题是,当我启动应用程序我还是不能 与“student1” /“密码”验证自己,但只与 默认的“用户” /。

这意味着默认用户(默认配置为AuthenticationManager)仍处于启用状态。为了解决这个问题,只是进样AuthenticationManagerBuilderconfigure方法:基于Spring boot documentation

@Override 
@Autowired 
protected void configure(AuthenticationManagerBuilder auth) throws Exception { ... } 

要同时关闭认证管理器配置,你可以 添加一个bean键入AuthenticationManager否则通过将AuthenticationManagerBuilder 自动装入您的@Configuration之一中的方法来配置全局的 AuthenticationManager类

因此,为了禁用默认AuthenticationManager,你应该Autowire一个AuthenticationManagerBuilder的配置方法。

我知道这是题外话,但下面这段代码看起来非常低效的对我说:

Iterable<Student> studentsWithIds = studentRepository.findAll(); 
for (Student student: studentsWithIds) { 
    if (student.getName() == username) { 
     return studentRepository.findOne(student.getId()); 
    } 
} 
+1

解释为什么他需要注入AuthenticationManagerBuilder可能会帮助OP理解他为什么有问题 – Turtle

+0

@Turtle更新了答案,感谢建议 –

+0

谢谢你,我试过你的建议,但只是增加@Autowired保护无效配置(AuthenticationManagerBuilder身份验证)抛出异常{...}似乎没有改变任何东西。有些东西还没有关闭。 (是的,这可能不是我如何从数据库中获取用户的最终版本,在这一点上我只是非常绝望,以至于我暂时不介意这样的快速和肮脏的事情)。 奇怪的是,我不认为执行甚至得到该配置方法,因为至少我应该看到一个UsernameNotFoundException不应该? – Andrel

相关问题