【问题标题】:Spring Security: how to pass additional user info to JSP?Spring Security:如何将其他用户信息传递给 JSP?
【发布时间】:2017-07-24 16:03:24
【问题描述】:

在 JSP 中,我可以通过 ${pageContext.request.remoteUser} 获取用户名。但是我还需要在网站的每个页面上显示其他信息(用户评分)。考虑到有一个@Service 可以通过用户名获取它,我该如何访问它?

我使用自定义身份验证提供程序的价值:

@Service
public class MyUserDetailsService implements UserDetailsService {
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        return new User(s, "password", Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));
    }
}
<security:authentication-manager>
    <security:authentication-provider user-service-ref='myUserDetailsService'/>
</security:authentication-manager>

【问题讨论】:

    标签: java spring jsp spring-security


    【解决方案1】:

    您可以创建自定义 UserDetails 类(例如 MyUserDetails)并将额外信息保存在那里。在您的 UserDetailsS​​ervice 中,只需返回此 MyUserDetails 而不是正常的 UserDetail。

    public class MyUserDetails extends UserDetail {
        private int rating;
        ... // other properties
        ... // getter setter
    }
    
    @Service
    public class MyUserDetailsService implements UserDetailsService {
        public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
            return new MyUserDetails(...);
        }
    }
    

    在每个控制器中,你可以调用

    (MyUserDetails)SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    

    获取当前的 principal/UserDetails,其中包含您的额外信息(例如用户的评分)。

    P.s.如果这些额外信息与用户有关,则会话不是存储它的正确位置,因为会话可能会在关闭浏览器后过期。如果这个额外的信息只是一些临时数据,那么@Branislav Lazic 的回答是正确的。由于我无法添加评论,所以我必须将 cmets 写到@Branislav Lazic 的答案这里。

    【讨论】:

    • 我不认为这是一些临时数据的问题。如果会话过期,用户将被简单地重定向到登录页面以更新他的会话,因此,它将重置额外的用户属性。在整个应用程序上下文中存储该属性可能非常危险!
    • @BranislavLazic 据我了解,用户的评分之类的东西可以作为用户的属性保存在数据库中。无论如何,它是在loadUserByUsername 函数中加载的。如果它是在会话期间设置的,那意味着它在不同的会话中可能会有所不同,这就是我的临时意思。在这种情况下,它当然应该存储在会话中,因为它是用户会话的属性。此外,重定向回登录页面和自动登录通常依赖于持久性 cookie。如果应用程序不提供该功能,则无法通过这种方式实现。
    • 即使你可以自动恢复会话,那么附加属性也是在所谓的“应用程序上下文”中,因为你可以随时检索它。 SecurityContext通常设置为threadLocal,如果配置了,也会保存在HttpSession中。恕我直言,它只会更安全。也许查看这个stackoverflow.com/questions/6408007/… 以获得一些解释。无论如何,这就是 Spring Security 提供给你使用的,为什么不简单地使用它
    【解决方案2】:

    您可以创建AuthenticationSuccessHandler 的实现并在那里设置一个属性:

    @Component
    public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {
        Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                Authentication authentication) throws IOException, ServletException {
            request.getSession().setAttribute("someDetail", "detailsValue");
            response.sendRedirect("/to-whatever-url-you-want")
        }
    }
    

    成功登录后,someDetail 属性将被设置。请注意,您也可以从Authentication 实例中获取当前登录的用户并执行一些逻辑。

    【讨论】:

    • 为未来的读者。将AuthenticationSuccessHandlerImpl 注册为登录表单处理程序也很重要。 &lt;security:http&gt; &lt;security:form-login authentication-success-handler-ref="authentificationSuccessHandlerImpl" /&gt; &lt;/security:http&gt;
    • @Jofsey 是的。在注解配置的情况下,在WebSecurityConfigurerAdapter impl。类,你可以像这样添加它:http.formLogin().loginPage("/login").failureUrl("/login?error").successHandler(new AuthenticationSuccessHandlerImpl())
    猜你喜欢
    • 2020-05-18
    • 2013-03-10
    • 2016-01-01
    • 2014-10-27
    • 1970-01-01
    • 2012-11-13
    • 2021-12-03
    • 1970-01-01
    • 2019-01-01
    相关资源
    最近更新 更多