关于SpringSecurity:在Servlet过滤器中访问当前经过身份验证的用户和springsecurity过滤器的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于java–Sprin
关于Spring Security:在Servlet过滤器中访问当前经过身份验证的用户和spring security 过滤器的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于java – Spring Security:未调用自定义UserDetailsService(使用Auth0身份验证)、JSP使用Servlet过滤器进行身份验证的方法、rest – curl通过经过身份验证的代理和经过身份验证的http资源、Spring Boot REST API / Spring Security:身份验证失败时返回自定义消息等相关知识的信息别忘了在本站进行查找喔。
本文目录一览:- Spring Security:在Servlet过滤器中访问当前经过身份验证的用户(spring security 过滤器)
- java – Spring Security:未调用自定义UserDetailsService(使用Auth0身份验证)
- JSP使用Servlet过滤器进行身份验证的方法
- rest – curl通过经过身份验证的代理和经过身份验证的http资源
- Spring Boot REST API / Spring Security:身份验证失败时返回自定义消息
Spring Security:在Servlet过滤器中访问当前经过身份验证的用户(spring security 过滤器)
我最近开始学习有关Spring
Security的知识,今天我提出了一个基本的(我相信)问题:为什么不能在Servlet过滤器中访问当前的Principal,如以下类所示:
package com.acme.test;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import org.springframework.security.core.Authentication;import org.springframework.security.core.context.SecurityContext;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.stereotype.Component;@Componentpublic class TestFilter implements Filter { /* * (non-Javadoc) * * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) */ @Override public void init(FilterConfig filterConfig) throws ServletException { // TODO Auto-generated method stub } /* * (non-Javadoc) * * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, * javax.servlet.ServletResponse, javax.servlet.FilterChain) */ @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { SecurityContext securityContext = SecurityContextHolder.getContext(); Authentication auth = securityContext.getAuthentication(); // auth is null here chain.doFilter(request, response); } /* * (non-Javadoc) * * @see javax.servlet.Filter#destroy() */ @Override public void destroy() { // TODO Auto-generated method stub }}
使用 auth 检索的Authentication对象 auth = securityContext.getAuthentication();
一片空白。在MVC @Controller中使用上述代码片段时,效果很好(如预期的那样)。
为什么会这样呢?
答案1
小编典典内部doFilter
:
HttpServletRequest request = (HttpServletRequest) request;HttpSession session = request.getSession(false);SecurityContextImpl sci = (SecurityContextImpl) session.getAttribute("SPRING_SECURITY_CONTEXT");if (sci != null) { UserDetails cud = (UserDetails) sci.getAuthentication().getPrincipal(); // do whatever you need here with the UserDetails}
希望这可以帮助
java – Spring Security:未调用自定义UserDetailsService(使用Auth0身份验证)
我正在使用Auth0来保护我的API,这非常有效.我的设置& config与Auth0文档中的suggested setup相同:
// SecurityConfig.java @Configuration @EnableWebSecurity(debug = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { // auth0 config vars here @Override protected void configure(HttpSecurity http) { JwtWebSecurityConfigurer .forRS256(apiAudience,issuer) .configure(http) .authorizeRequests() .antMatchers(HttpMethod.GET,"/api/public").permitAll() .antMatchers(HttpMethod.GET,"/api/private").authenticated(); } }
使用此设置,spring安全主体从jwt标记设置为userId(sub):auth0 | 5b2b ….但是,我希望它设置为匹配用户(来自我的数据库)而不仅仅是userId .我的问题是如何做到这一点.
我试过的
我已经尝试实现从this tutorial复制的自定义数据库支持的UserDetailsService.
然而,无论我如何尝试将其添加到我的conf中,它都不会被调用.我尝试过几种不同的方式添加它没有效果:
// SecurityConfig.java (changes only) // My custom userDetailsService,overriding the loadUserByUsername // method from Spring Framework's UserDetailsService. @Autowired private MyUserDetailsService userDetailsService; protected void configure(HttpSecurity http) { http.userDetailsService(userDetailsService); // Option 1 http.authenticationProvider(authenticationProvider()); // Option 2 JwtWebSecurityConfigurer [...] // The rest unchanged from above } @Override // Option 3 & 4: Override the following method protected void configure(AuthenticationManagerBuilder auth) { auth.authenticationProvider(authenticationProvider()); // Option 3 auth.userDetailsService(userDetailsService); // Option 4 } @Bean // Needed for Options 2 or 4 public DaoAuthenticationProvider authenticationProvider() { DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); authProvider.setUserDetailsService(userDetailsService); return authProvider; }
不幸的是,由于我需要将其与Auth0身份验证相结合,所以没有类似的“userDetails not called called”问题帮助了我.
我并不认为我正走在正确的道路上.我觉得很奇怪,在这个极为常见的用例中我找不到Auth0的任何文档,所以也许我错过了一些明显的东西.
PS:不确定是否相关,但在init期间始终记录以下内容.
Jun 27,2018 11:25:22 AM com.test.UserRepository initDao INFO: No authentication manager set. Reauthentication of users when changing passwords will not be performed.
编辑1:
根据Ashish451的回答,我尝试复制他的CustomUserDetailsService,并将以下内容添加到我的SecurityConfig中:
@Autowired private CustomUserDetailsService userService; @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Autowired public void configureGlobal( AuthenticationManagerBuilder auth ) throws Exception { auth.userDetailsService( userService ); }
不幸的是,通过这些更改,仍未调用CustomUserDetailsService.
编辑2:
添加@norberto Ritzmann建议的日志记录方法时的输出:
Jul 04,2018 3:49:22 PM com.test.repositories.UserRepositoryImpl initDao INFO: No authentication manager set. Reauthentication of users when changing passwords will not be performed. Jul 04,2018 3:49:22 PM com.test.runner.JettyRunner testUserDetailsImpl INFO: UserDetailsService implementation: com.test.services.CustomUserDetailsService
解决方法
我不知道什么是apiAudience,发行人,但它产生了JWT的子猜测.
您的问题是您希望根据数据库更改JWT子.
我最近在Spring Boot Application中实现了JWT安全性.
我从数据库中获取UserName之后设置它.
为清楚起见,我添加了带pkg信息的代码.
//我的适配器类和你的一样,除了我添加过滤器的一件事.在此过滤器中,我正在验证JWT令牌.每次触发安全休息URL时都会调用此过滤器.
import java.nio.charset.StandardCharsets; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.www.BasicAuthenticationFilter; import org.thymeleaf.Spring5.SpringTemplateEngine; import org.thymeleaf.Spring5.templateresolver.SpringResourceTemplateResolver; import com.dev.myapp.jwt.model.CustomUserDetailsService; import com.dev.myapp.security.RestAuthenticationEntryPoint; import com.dev.myapp.security.TokenAuthenticationFilter; import com.dev.myapp.security.TokenHelper; @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Autowired private CustomUserDetailsService jwtUserDetailsService; // Get UserDetail bu UserName @Autowired private RestAuthenticationEntryPoint restAuthenticationEntryPoint; // Handle any exception during Authentication @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } // Binds User service for User and Password Query from Database with Password Encryption @Autowired public void configureGlobal( AuthenticationManagerBuilder auth ) throws Exception { auth.userDetailsService( jwtUserDetailsService ) .passwordEncoder( passwordEncoder() ); } @Autowired TokenHelper tokenHelper; // Contains method for JWT key Generation,Validation and many more... @Override protected void configure(HttpSecurity http) throws Exception { http .sessionManagement().sessionCreationPolicy( SessionCreationPolicy.STATELESS ).and() .exceptionHandling().authenticationEntryPoint( restAuthenticationEntryPoint ).and() .authorizeRequests() .antMatchers("/auth/**").permitAll() .anyRequest().authenticated().and() .addFilterBefore(new TokenAuthenticationFilter(tokenHelper,jwtUserDetailsService),BasicAuthenticationFilter.class); http.csrf().disable(); } // Patterns to ignore from JWT security check @Override public void configure(WebSecurity web) throws Exception { // TokenAuthenticationFilter will ignore below paths web.ignoring().antMatchers( HttpMethod.POST,"/auth/login" ); web.ignoring().antMatchers( HttpMethod.GET,"/","/assets/**","/*.html","/favicon.ico","/**/*.html","/**/*.css","/**/*.js" ); } }
//用户服务获取用户详细信息
@Transactional @Repository public class CustomUserDetailsService implements UserDetailsService { protected final Log LOGGER = LogFactory.getLog(getClass()); @Autowired private UserRepo userRepository; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { User uu = userRepository.findByUsername(username); if (user == null) { throw new UsernameNotFoundException(String.format("No user found with username '%s'.",username)); } else { return user; } } }
//未经授权的访问处理程序
@Component public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request,HttpServletResponse response,AuthenticationException authException) throws IOException { // This is invoked when user tries to access a secured REST resource without supplying any credentials response.sendError(HttpServletResponse.SC_UNAUTHORIZED,authException.getMessage()); } }
//用于验证JWT令牌的过滤链
import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.servletexception; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.web.filter.OncePerRequestFilter; public class TokenAuthenticationFilter extends OncePerRequestFilter { protected final Log logger = LogFactory.getLog(getClass()); private TokenHelper tokenHelper; private UserDetailsService userDetailsService; public TokenAuthenticationFilter(TokenHelper tokenHelper,UserDetailsService userDetailsService) { this.tokenHelper = tokenHelper; this.userDetailsService = userDetailsService; } @Override public void doFilterInternal( HttpServletRequest request,FilterChain chain ) throws IOException,servletexception { String username; String authToken = tokenHelper.getToken(request); logger.info("AuthToken: "+authToken); if (authToken != null) { // get username from token username = tokenHelper.getUsernameFromToken(authToken); logger.info("UserName: "+username); if (username != null) { // get user UserDetails userDetails = userDetailsService.loadUserByUsername(username); if (tokenHelper.validatetoken(authToken,userDetails)) { // create authentication TokenBasedAuthentication authentication = new TokenBasedAuthentication(userDetails); authentication.setToken(authToken); SecurityContextHolder.getContext().setAuthentication(authentication); // Adding Token in Security COntext } }else{ logger.error("Something is wrong with Token."); } } chain.doFilter(request,response); } }
// TokenBasedAuthentication类
import org.springframework.security.authentication.AbstractAuthenticationToken; import org.springframework.security.core.userdetails.UserDetails; public class TokenBasedAuthentication extends AbstractAuthenticationToken { private static final long serialVersionUID = -8448265604081678951L; private String token; private final UserDetails principle; public TokenBasedAuthentication( UserDetails principle ) { super( principle.getAuthorities() ); this.principle = principle; } public String getToken() { return token; } public void setToken( String token ) { this.token = token; } @Override public boolean isAuthenticated() { return true; } @Override public Object getCredentials() { return token; } @Override public UserDetails getPrincipal() { return principle; } }
// JWT生成和验证逻辑的助手类
import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import java.util.Date; import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; import com.dev.myapp.common.TimeProvider; import com.dev.myapp.entity.User; @Component public class TokenHelper { protected final Log LOGGER = LogFactory.getLog(getClass()); @Value("${app.name}") // reading details from property file added in Class path private String APP_NAME; @Value("${jwt.secret}") public String SECRET; @Value("${jwt.licenseSecret}") public String LICENSE_SECRET; @Value("${jwt.expires_in}") private int EXPIRES_IN; @Value("${jwt.mobile_expires_in}") private int MOBILE_EXPIRES_IN; @Value("${jwt.header}") private String AUTH_HEADER; @Autowired TimeProvider timeProvider; // return current time. Basically Deployment time. private SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS512; // Generate Token based on UserName. You can Customize this public String generatetoken(String username) { String audience = generateAudience(); return Jwts.builder() .setIssuer( APP_NAME ) .setSubject(username) .setAudience(audience) .setIssuedAt(timeProvider.Now()) .setExpiration(generateExpirationDate()) .signWith( SIGNATURE_ALGORITHM,SECRET ) .compact(); } public Boolean validatetoken(String token,UserDetails userDetails) { User user = (User) userDetails; final String username = getUsernameFromToken(token); final Date created = getIssuedAtDateFromToken(token); return ( username != null && username.equals(userDetails.getUsername()) ); } // If Token is valid will extract all claim else throw appropriate error private Claims getAllClaimsFromToken(String token) { Claims claims; try { claims = Jwts.parser() .setSigningKey(SECRET) .parseClaimsJws(token) .getBody(); } catch (Exception e) { LOGGER.error("Could not get all claims Token from passed token"); claims = null; } return claims; } private Date generateExpirationDate() { long expiresIn = EXPIRES_IN; return new Date(timeProvider.Now().getTime() + expiresIn * 1000); } }
对于这个日志
No authentication manager set. Reauthentication of users when changing passwords
由于尚未使用Name loadUserByUsername实现方法.你得到这个日志.
编辑1:
我正在使用Filter Chain来验证令牌并在安全上下文中添加用户,这将从令牌中提取….
使用JWT并且您使用的是AuthO,只有实现不同.我为完整的工作流程添加了完整的实施.
您专注于从WebSecurityConfig类实现authenticationManagerBean和configureGlobal以使用UserService.
和TokenBasedAuthentication类实现.
其他你可以跳过的东西.
JSP使用Servlet过滤器进行身份验证的方法
这篇文章主要介绍了JSP使用Servlet过滤器进行身份验证的方法,结合实例形式分析了Servlet过滤器的实现方法及jsp身份验证的具体使用技巧,需要的朋友可以参考下
本文实例讲述了JSP使用Servlet过滤器进行身份验证的方法。分享给大家供大家参考,具体如下:
1、Servlet过滤器的作用描述
(1)在HttpServletRequest到达Servlet 之前,拦截客户的HttpServletRequest。
根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据。
(2)在HttpServletResponse 到达客户端之前,拦截HttpServletResponse。
根据需要检查HttpServletResponse,可以修改HttpServletResponse头和数据。
2、应用Servlet过滤器进行身份验证
假设网站根目录下的login1.htm、longin1.jsp用于用户登录,而chap08目录下的文件需要用户登录后才能访问。
(1)编写Servlet过滤器
@WebFilter("/FilterStation") public class FilterStation extends HttpServlet implements Filter { private FilterConfig filterConfig; public FilterStation() { super(); } public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, servletexception { HttpSession session=((HttpServletRequest)request).getSession(); response.setCharacterEncoding("gb2312"); if(session.getAttribute("me")==null){ PrintWriter out=response.getWriter(); out.print(""); } else{ // pass the request along the filter chain chain.doFilter(request, response); } } public void init(FilterConfig fConfig) throws servletexception { // Todo Auto-generated method stub this.filterConfig=fConfig; } }
(2)配置web.xml
filterstationzhou.FilterStationfilterstation/chap08/*
(3)login1.htm代码
用户登录
用户名:
密码:
(4)login1.jsp代码
Session 应用演示
希望本文所述对大家JSP程序设计有所帮助。
rest – curl通过经过身份验证的代理和经过身份验证的http资源
如果我没有代理
curl -u user:pass -d status="message" http://twitter.com/statuses/update.xml
工作得很好.
但是,当我在经过身份验证的代理服务器后面时却没有.
我试过了:
curl -X proxy:port -U proxyUser:proxyPass -u user:pass -d status="message" http://twitter.com/statuses/update.xml
它让我跳了起来
proxy do not support basic auth
所以你知道我做错了什么吗?
提前致谢.
解决方法
>关于connect()到代理[your proxy] port [your port](#0)
>尝试[IP] ……
>连接
>连接到[您的代理]([IP])端口[您的端口](#0)
>建立到www.google.com:443的HTTP代理隧道
>使用Basic与用户'[user]’进行代理验证
> CONNECT www.google.com:443 HTTP / 1.1
>主持人:www.google.com:443
>代理授权:基本[乱码]
> User-Agent:curl / [ver]([OS])libcurl / [ver] OpenSSL / [ver] zlib / [ver]
>代理连接:保持活跃
> HTTP / 1.1 407需要代理身份验证
>代理 – 身份验证:NEGOTIATE
>代理 – 身份验证:NTLM
为您在Proxy-Authenticate参数中看到的任何内容添加标记,您应该很高兴.在此示例中,您将添加–proxy-ntlm标志.
Spring Boot REST API / Spring Security:身份验证失败时返回自定义消息
我有一个使用Jersey作为JAX-RS实现的Spring Boot应用程序。这是我的安全配置:
@Configuration@EnableGlobalMethodSecurity(prePostEnabled = true)@EnableWebSecuritypublic class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired TokenAuthenticationProvider tokenAuthenticationProvider; @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(tokenAuthenticationProvider); } @Override protected void configure(HttpSecurity http) throws Exception { http.addFilterBefore(new AuthenticationTokenFilter(), BasicAuthenticationFilter.class) .csrf().disable() .authorizeRequests() .antMatchers("/dataHub/**") .authenticated(); }}
我想要做的是有一种方法来捕获我的TokenAuthenticationProvider抛出的异常,并将其转换为我们已经同意的标准化JSON格式。有没有办法做到这一点?我尝试添加自定义AuthenticationFailureHandler,但无法正常工作。
答案1
小编典典WebSecurityConfigurerAdapter方法
的HttpSecurity
类有一个叫做方法exceptionHandling可用于覆盖默认行为。以下示例介绍了如何自定义响应消息。
@Overrideprotected void configure(HttpSecurity http) throws Exception { http // your custom configuration goes here .exceptionHandling() .authenticationEntryPoint((request, response, e) -> { String json = String.format("{\"message\": \"%s\"}", e.getMessage()); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); response.getWriter().write(json); });}
@ControllerAdvice方法-为什么在这种情况下不起作用
最初,我想到的@ControllerAdvice
是捕获整个应用程序的身份验证异常。
import org.springframework.http.HttpStatus;import org.springframework.security.core.AuthenticationException;@ControllerAdvicepublic class AuthExceptionHandler { @ResponseStatus(HttpStatus.UNAUTHORIZED) @ExceptionHandler(AuthenticationException.class) @ResponseBody public String handleAuthenticationException(AuthenticationException e) { return String.format("{\"message\": \"%s\"}", e.getMessage()); }}
在上面的示例中,JSON是手动构建的,但是您可以简单地返回一个POJO,该POJO将被映射到JSON中,就像从常规REST控制器中一样。既然Spring
4.3,你也可以使用@RestControllerAdvice,这是一个组合@ControllerAdvice
和@ResponseBody
。
但是,这种方法行不通,
因为在到达任何控制器之前,该异常将由抛出AbstractSecurityInterceptor
并由ExceptionTranslationFilter处理。
关于Spring Security:在Servlet过滤器中访问当前经过身份验证的用户和spring security 过滤器的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于java – Spring Security:未调用自定义UserDetailsService(使用Auth0身份验证)、JSP使用Servlet过滤器进行身份验证的方法、rest – curl通过经过身份验证的代理和经过身份验证的http资源、Spring Boot REST API / Spring Security:身份验证失败时返回自定义消息的相关信息,请在本站寻找。
本文标签: