2016-05-12 64 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

相關問題