- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个带有 JWT 身份验证的小型 Spring Boot 2.1.6 Web 应用程序。调用流程如下:
此外,CSRF 在 WebSecurityConfigurerAdapter 中被禁用。
解决方案本身工作正常,但我还必须创建单元测试。我最终得到了以下测试用例:
@RunWith(SpringRunner.class)
@WebMvcTest
@ContextConfiguration(classes = { ConfigReaderMock.class })
public class ControllerSecurityTest {
private static final String VALID_USERNAME = "username";
private static final String VALID_PASSWORD = "password";
@Autowired
private MockMvc mockMvc;
private String createAuthenticationBody(String username, String passwordHash) {
return "username=" + URLEncoder.encode(username, StandardCharsets.UTF_8) + "&password="
+ URLEncoder.encode(passwordHash, StandardCharsets.UTF_8);
}
@Test
public void testValidLogin() throws Exception {
MvcResult result = mockMvc
.perform(MockMvcRequestBuilders.post("/authenticate")
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.content(createAuthenticationBody(VALID_USERNAME, VALID_PASSWORD)).accept(MediaType.ALL))
.andExpect(status().isOk()).andReturn();
String authHeader = result.getResponse().getHeader(SecurityConstants.TOKEN_HEADER);
mockMvc.perform(MockMvcRequestBuilders.get("/main?" + SecurityConstants.TOKEN_QUERY_PARAM + "="
+ URLEncoder.encode(authHeader, StandardCharsets.UTF_8))).andExpect(status().isOk());
}
}
我期望的是,服务器接受提供的用户名和密码,并返回 JWT,我可以在后续请求中使用它来访问下一个页面(前端也实现了相同的功能)。相反,我从身份验证过滤器获取 HTTP 403:
MockHttpServletRequest:
HTTP Method = POST
Request URI = /authenticate
Parameters = {username=[username], password=[password]}
Headers = [Content-Type:"application/x-www-form-urlencoded", Accept:"*/*"]
Body = <no character encoding set>
Session Attrs = {org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN=org.springframework.security.web.csrf.DefaultCsrfToken@4ac0fdc7}
Handler:
Type = null
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 403
Error message = Forbidden
Headers = [X-Content-Type-Options:"nosniff", X-XSS-Protection:"1; mode=block", Cache-Control:"no-cache, no-store, max-age=0, must-revalidate", Pragma:"no-cache", Expires:"0", X-Frame-Options:"DENY"]
Content type = null
Body =
Forwarded URL = null
Redirected URL = null
Cookies = []
我注意到它出于某种原因在 session 属性中发送 CSRF token 。进一步检查日志,我可以看到以下消息:
2019-07-29 08:09:17,438 DEBUG o.s.b.f.s.DefaultSingletonBeanRegistry [main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.security.servlet.WebSecurityEnablerConfiguration'
2019-07-29 08:09:17,443 DEBUG o.s.s.c.a.a.c.AuthenticationConfiguration$EnableGlobalAuthenticationAutowiredConfigurer [main] Eagerly initializing {org.springframework.boot.autoconfigure.security.servlet.WebSecurityEnablerConfiguration=org.springframework.boot.autoconfigure.security.servlet.WebSecurityEnablerConfiguration$$EnhancerBySpringCGLIB$$236da03c@4e68aede}
2019-07-29 08:09:17,444 DEBUG o.s.b.f.s.DefaultSingletonBeanRegistry [main] Creating shared instance of singleton bean 'inMemoryUserDetailsManager'
2019-07-29 08:09:17,445 DEBUG o.s.b.f.s.DefaultSingletonBeanRegistry [main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration'
2019-07-29 08:09:17,454 DEBUG o.s.b.f.s.DefaultSingletonBeanRegistry [main] Creating shared instance of singleton bean 'spring.security-org.springframework.boot.autoconfigure.security.SecurityProperties'
2019-07-29 08:09:17,457 DEBUG o.s.b.f.s.ConstructorResolver [main] Autowiring by type from bean name 'inMemoryUserDetailsManager' via factory method to bean named 'spring.security-org.springframework.boot.autoconfigure.security.SecurityProperties'
2019-07-29 08:09:17,462 INFO o.s.b.a.s.s.UserDetailsServiceAutoConfiguration [main]
Using generated security password: 963b2bac-d953-4793-a8cd-b3f81586823e
...
2019-07-29 08:09:17,783 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository [main] No HttpSession currently exists
2019-07-29 08:09:17,784 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository [main] No SecurityContext was available from the HttpSession: null. A new one will be created.
2019-07-29 08:09:17,794 DEBUG o.s.s.w.c.CsrfFilter [main] Invalid CSRF token found for http://localhost/authenticate
2019-07-29 08:09:17,795 DEBUG o.s.s.w.h.w.HstsHeaderWriter [main] Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@1c15a6aa
2019-07-29 08:09:17,796 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper [main] SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2019-07-29 08:09:17,799 DEBUG o.s.s.w.c.SecurityContextPersistenceFilter [main] SecurityContextHolder now cleared, as request processing completed
因此,Spring Security 似乎正在创建自己的安全配置,而不是使用我创建的类来扩展 WebSecurityConfigurerAdapter。问题是,为什么?我如何强制它使用我的安全配置,因为我的数据库登录依赖于它?
更新:添加了 WebSecurityConfigurerAdapter
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AICAuthenticationService authenticationService;
@Autowired
private AICUserDetailsService aicUserDetailsService;
@Autowired
private AICLogoutSuccessHandler aicLogoutSuccessHandler;
@Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.cors()
.and()
.authorizeRequests()
.antMatchers("/resources/**", "/login", "/").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.addFilter(new JwtAuthorizationFilter(authenticationManager()))
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(aicLogoutSuccessHandler)
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID", "error");
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(aicUserDetailsService);
}
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return authenticationService;
}
@Bean
public AuthenticationManager custromAuthenticationManager() throws Exception {
return authenticationManager();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(aicUserDetailsService);
}
最佳答案
我能够使用 TestRestTemplate 完成它,如下所示:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class ControllerSecurityTest {
private static final String VALID_USERNAME = "username";
private static final String VALID_PASSWORD = "password";
@LocalServerPort
private int port;
@Autowired
private TestRestTemplate restTemplate;
@Test
public void testValidLogin() throws Exception {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.setAccept(Arrays.asList(MediaType.ALL));
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("username", VALID_USERNAME);
map.add("password", VALID_PASSWORD);
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
ResponseEntity<String> tokenResponse = restTemplate
.postForEntity("http://localhost:" + port + "/authenticate", request, String.class);
assertEquals(200, tokenResponse.getStatusCodeValue());
String authHeader = tokenResponse.getHeaders().getFirst(SecurityConstants.TOKEN_HEADER);
assertNotNull(authHeader);
ResponseEntity<String> mainResponse = restTemplate.getForEntity("http://localhost:" + port + "/main?"
+ SecurityConstants.TOKEN_QUERY_PARAM + "=" + URLEncoder.encode(authHeader, StandardCharsets.UTF_8),
String.class);
assertEquals(200, mainResponse.getStatusCodeValue());
}
}
关于java - 如何使用 Spring security 测试基于数据库的用户的 JWT 身份验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57248292/
在为 Web 应用程序用例图建模时,为用户可以拥有的每个角色创建一个角色是否更好?或拥有一个角色、用户和一个具有特权的矩阵? guest < 用户 < 版主 < 管理员 1: guest 、用户、版主
我无法使用 Elixir 连接到 Postgres: ** (Mix) The database for PhoenixChat.Repo couldn't be created: FATAL 28P
这个问题已经有答案了: Group by field name in Java (7 个回答) 已关闭 7 年前。 我必须编写一个需要 List 的方法并返回 Map> . User包含 Person
感谢您的帮助,首先我将显示代码: $dotaz = "Select * from customers JOIN contracts where customers.user_id ='".$_SESS
我只想向所有用户中的一个用户显示一个按钮。我尝试了 orderByKey() 但没有成功! 用户模型有 id 成员,我尝试使用 orderByChild("id") 但结果相同! 我什至尝试了以下技巧
我们在工作中从 MongoDB 切换到 Postgres,我正在建立一个 BDR 组。 在这一步,我正在考虑安全性并尽可能锁定。因此,我希望设置一个 replication 用户(角色)并让 BDR
export class UserListComponent implements OnInit{ users; constructor(private userService: UserS
我可以使用 Sonata User Bundle 将 FOS 包集成到 sonata Admin 包中。我的登录功能正常。现在我想添加 FOSUserBundle 中的更改密码等功能到 sonata
在 LinkedIn 中创建新应用程序时,我得到 4 个单独的代码: API key 秘钥 OAuth 用户 token OAuth 用户密码 我在 OAuth 流程中使用前两个。 的目的是什么?最后
所以..我几乎解决了所有问题。但现在我要处理另一个问题。我使用了这个连接字符串: SqlConnection con = new SqlConnection(@"Data Source=.\SQLEX
我有一组“用户”和一组“订单”。我想列出每个 user_id 的所有 order_id。 var users = { 0: { user_id: 111, us
我已经为我的Django应用创建了一个用户模型 class User(Model): """ The Authentication model. This contains the u
我被这个问题困住了,找不到解决方案。寻找一些方向。我正在用 laravel 开发一个新的项目,目前正致力于用户认证。我正在使用 Laravels 5.8 身份验证模块。 对密码恢复 View 做了一些
安装后我正在使用ansible配置几台计算机。 为此,我在机器上本地运行 ansible。安装中的“主要”用户通常具有不同的名称。我想将该用户用于诸如 become_user 之类的变量. “主要”用
我正在尝试制作一个运行 syncdb 的批处理文件来创建一个数据库文件,然后使用用户名“admin”和密码“admin”创建一个 super 用户。 到目前为止我的代码: python manage.
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 6 年前。 Improv
我已在 Azure 数据库服务器上设置异地复制。 服务器上运行的数据库之一具有我通过 SSMS 创建的登录名和用户: https://learn.microsoft.com/en-us/azure/s
我有一个 ionic 2 应用程序,正在使用 native FB Login 来检索名称/图片并将其保存到 NativeStorage。流程是我打开WelcomePage、登录并保存数据。从那里,na
这是我的用户身份验证方法: def user_login(request): if request.method == 'POST': username = request.P
我试图获取来自特定用户的所有推文,但是当我迭代在模板中抛出推文时,我得到“User”对象不可迭代 观看次数 tweets = User.objects.get(username__iexact='us
我是一名优秀的程序员,十分优秀!