Java 弹簧:将用户设置为";中的参数;“全部”;控制器和控制器功能(代替主体)

Java 弹簧:将用户设置为";中的参数;“全部”;控制器和控制器功能(代替主体),java,spring,spring-security,principal,Java,Spring,Spring Security,Principal,在一个简单的Web应用程序中,我可以检索一个用户(从会话属性),并使用过滤器将其设置为所有servlet的参数: 内部过滤器: @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { checkUser((HttpServletRequest) request);

在一个简单的Web应用程序中,我可以检索一个用户(从会话属性),并使用过滤器将其设置为所有servlet的参数:

内部过滤器:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    checkUser((HttpServletRequest) request);
    chain.doFilter(request, response);
}

private void checkUser(HttpServletRequest request) {
    HttpSession session = request.getSession(false);
    if (session != null) {
        request.setAttribute("user", session.getAttribute("user"));
    }
}
public String getDisplayName() {
    if (firstname == null && lastname == null) {
        return username;
    }
    if (firstname != null && lastname != null) {
        return String.format("%s %s", firstname, lastname);
    }
    if (firstname != null) {
        return firstname;
    }
    return lastname;
}
然后我可以在我的JSP文件中使用它(
blablabla
):


在Spring应用程序中,我必须在每个控制器函数中注入主体。即使在这种情况下,主体也不是用户,因此每次我都需要使用UserService:

@Controller
@RequestMapping("/")
public class IndexController {

    private final UserService userService;

    @Autowired
    IndexController(UserService userService) {
        this.userService = userService;
    }

    private static final String VIEW = "index";

    @RequestMapping(method = RequestMethod.GET)
    ModelAndView index(Principal principal) {
        User user = null;
        if (principal != null) {
            user = userService.findByUsername(principal.getName());
        }
        return new ModelAndView(VIEW, "user", user);
    }
}

我需要user(entity类)对象,因为它有我使用的不同函数。例如,我用于导航栏(每页上)的
getDisplayName()

用户类:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    checkUser((HttpServletRequest) request);
    chain.doFilter(request, response);
}

private void checkUser(HttpServletRequest request) {
    HttpSession session = request.getSession(false);
    if (session != null) {
        request.setAttribute("user", session.getAttribute("user"));
    }
}
public String getDisplayName() {
    if (firstname == null && lastname == null) {
        return username;
    }
    if (firstname != null && lastname != null) {
        return String.format("%s %s", firstname, lastname);
    }
    if (firstname != null) {
        return firstname;
    }
    return lastname;
}
我无法在Spring Framework中使用安全标记库函数使用此特定用户函数(getDisplayName):

<security:authentication property="name"/> <%-- So, this is not what I am looking for --%>


好的,我甚至尝试创建一个自定义拦截器并注册它(我不想做的事情,因为我每次都要从数据库中再次读取我的用户)。但是,我在拦截器中自动连接UserService时遇到了问题


解决这个问题的最好办法是什么?是否可以在成功登录后从数据库(findByUsername)中查找一次用户,然后将其放入会话中,然后制作一种拦截器,它可以像我以前使用过滤器一样执行操作,或者每次从数据库中检索每个页面的用户,但要避免这种迂回的重复代码?

您可以提供一个登录成功处理程序,如

http.formLogin().successHandler(new AuthenticationSuccessHandler() {

            @Override
            public void onAuthenticationSuccess(HttpServletRequest arg0,
                    HttpServletResponse arg1, Authentication arg2) throws IOException,
                    ServletException {
                // here you can put your logic to save User object into session then forward/redirect to where ever you want

            }
        })
或者,您也可以将登录成功转发到某个端点,如

http.formLogin().successForwardUrl("/loginsuccess")
并提供endpont实现,如

@RequestMapping({ "/loginsuccess" })
    public ResponseEntity<?> loginSuccess(Principal user) {

        // here you can put your logic to save User object into session then forward/redirect to where ever you want

        return "";
    }
@RequestMapping({”/loginsucess})
公共响应登录成功(主要用户){
//在这里,您可以将您的逻辑保存到会话中,然后转发/重定向到您想要的任何地方
返回“”;
}

选择您觉得更方便的方式。

已解决:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    checkUser((HttpServletRequest) request);
    chain.doFilter(request, response);
}

private void checkUser(HttpServletRequest request) {
    HttpSession session = request.getSession(false);
    if (session != null) {
        request.setAttribute("user", session.getAttribute("user"));
    }
}
public String getDisplayName() {
    if (firstname == null && lastname == null) {
        return username;
    }
    if (firstname != null && lastname != null) {
        return String.format("%s %s", firstname, lastname);
    }
    if (firstname != null) {
        return firstname;
    }
    return lastname;
}
我制作了一个自定义拦截器,向其中注入了一个自动连接的用户服务,并注册了该自定义拦截器。它起作用了

public class MyWebConfig extends WebMvcConfigurerAdapter {
    @Bean
    public UsernameInjectionInterceptor usernameInjectionInterceptor() {
        return new UsernameInjectionInterceptor();
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(usernameInjectionInterceptor());
    }
}