GVKun编程网logo

Spring Security:在Servlet过滤器中访问当前经过身份验证的用户(spring security 过滤器)

14

关于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 过滤器)

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身份验证)

java – Spring Security:未调用自定义UserDetailsService(使用Auth0身份验证)

我是 Spring框架的新手,所以我提前为我理解中的任何漏洞道歉.

我正在使用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复制的自定义数据库支持的UserDetailsS​​ervice.
然而,无论我如何尝试将其添加到我的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的回答,我尝试复制他的CustomUserDetailsS​​ervice,并将以下内容添加到我的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 );
}

不幸的是,通过这些更改,仍未调用CustomUserDetailsS​​ervice.

编辑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

解决方法

查看您的适配器代码,您将在配置中生成JWT令牌.
我不知道什么是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过滤器进行身份验证的方法

这篇文章主要介绍了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资源

rest – curl通过经过身份验证的代理和经过身份验证的http资源

我想用oneliner做一个帖子(本例中是twitter).

如果我没有代理

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

所以你知道我做错了什么吗?

提前致谢.

解决方法

Cababunga的答案是正确的,但他们错过了另一种选择: – proxy-ntlm.某些代理不会使用–proxy-anyauth正确授权,因此理想情况下,您需要指定代理使用的身份验证方法.如果你运行curl -v -U user:pass -x proxy:port –url http://www.google.com,你应该得到以下内容:

>关于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:身份验证失败时返回自定义消息

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:身份验证失败时返回自定义消息的相关信息,请在本站寻找。

本文标签: