如何处理登录用户而不是在同一控制器中登录用户?

时间:2017-04-14 00:27:12

标签: java spring spring-mvc spring-security

让我们说我有一个带有Spring Security的Spring MVC。我有一个控制器方法,我想得到我祖母的食谱。

RequestMapping(value="/Recipe/{recipeId}", method = RequestMethod.GET)
Public Recipe getRecipe(@PathVariable("recipeId") int recepieId) {

 Recipe recipe = database.getRecipeById(recepieId);
 if(recipe.isBisket()) {
      return recipe;   
 }

 if(recipe.isSecretCookieRecipe()) {
     boolean isAuthenitacted = Utils.authenticatUser(user);
     if(isAuthenticated() {
          return recipe;
     } else {
          // do something to authenitcate and then return the recipie
     }
  }
}

现在问题出在Spring安全上下文中。如果我做这样的事情:

<security:intercept-url pattern="/Recipe/*" access="IS_AUTHENTICATED_FULLY" />

<beans:bean id="authenticationSuccessHandler" class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">   
   <beans:property name="useReferer" value="true" />
</beans:bean>

现在显然在这种情况下,isAuthenticated()将始终返回true,因为拦截模式将处理它。所以让我删除拦截网址,并尝试这个REST URL CALL:

GET http://bestrecepiesever/Recipe/1

现在1是一个biskett配方,所以任何人都可以得到它并且通话有效。现在我想要一个cookie,所以我试试这个:

GET http://bestrecepiesever/Recipe/420

现在我的Utils类将检查我的会话,看到我没有记录它并抛出异常。这就是我的问题所在......我希望能够为http://bestrecepiesever/Recipe/420添加书签。当我去那里时,我会重新登录我的登录页面,登录后,我会被重新定向回配方。

如何使用Spring Security执行此操作?我放在哪里//做一些事情来进行身份验证会发现我此时未经过身份验证,请将我发送到登录页面,然后再返回配方。

为了使事情变得复杂,我们有SimpleMappingExceptionResolver来拦截任何和所有异常,并将您重定向到一个很好的页面找不到。是的,我尝试创建自己的,重定向到登录页面,这是有效的,但不会回到referer页面。你可以在这里看到这个问题:Overriding HandlerExceptionResolver not useing Referer

更新

根据@chaoluo这里是utils中的getAuthentication方法:

public static User getUser(IDaoFactory daoFactory) throws Exception {
    String authClass = SecurityContextHolder.getContext().getAuthentication().getPrincipal().getClass().getName();
    authClass = SecurityContextHolder.getContext().getAuthentication().getAuthorities().getClass().getName();
    if (authClass == null) {
        authClass = "[ unknown ]";
    }

    if (SecurityContextHolder.getContext().getAuthentication().getName().toLowerCase().equals("anonymoususer")) {
        throw new Exception("not authorized");
    }
    User theUser = new MyUserDetailsService(daoFactory).loadUserByUsername(SecurityContextHolder.getContext().getAuthentication().getName());
    if (theUser == null) {
        logger.error("Unable to find user in DB for " + SecurityContextHolder.getContext().getAuthentication().getName());
    }
    return theUser;
}

但是,这与SpringSecurity中使用的MyAuthenticationProvider完全不同,如下所示:

<security:authentication-manager alias="authenticationManager">
    <security:authentication-provider ref="myAuthenticationProvider"/>       
    </security:authentication-provider>
</security:authentication-manager>

验证方法:

@Override
    public Authentication authenticate(Authentication authentication) 
    throws AuthenticationException 
{
    String username = authentication.getName();
    String password = (String) authentication.getCredentials();
    //System.out.println(org.apache.commons.lang.exception.ExceptionUtils.getStackTrace(Throwable));
    IDaoFactory daoFactory = ServiceFactory.getDaoFactory();
    try {
        QadoUserDetailsService userService = new QadoUserDetailsService(daoFactory);
        User user = userService.loadUserByUsername(username);

        if (user == null) {
            throw new BadCredentialsException(BAD_USER);
        }
        if (user.getPassword() == null || user.getSalt() == null || 
            !PasswordEncryption.hashEquals(user.getSalt(), user.getPassword(), password)) {
            throw new BadCredentialsException(BAD_PASSWORD);
        }

        Collection<? extends GrantedAuthority> authorities = user.getAuthorities();
        return new UsernamePasswordAuthenticationToken(username, password, authorities);
    }
    finally {
        daoFactory.cleanup();
    }
}

那么有没有办法通过控制器内的MyAuthenticationProvider进行身份验证?

1 个答案:

答案 0 :(得分:0)

你正在使事情复杂化。而不是@PreAuthorize使用@PostAuthorize来进行验证。这将使您的控制器保持清洁,让Spring Security处理这些事情。

@RequestMapping(value="/Recipe/{recipeId}", method = RequestMethod.GET)
@PostAuthorize("returnObject.bisket || (returnObject.secretCookieRecipe && isAuthenticated())")
public Recipe getRecipe(@PathVariable("recipeId") int recepieId) {

 return database.getRecipeById(recepieId);

}

现在,Spring Security将使用当前用户验证returnObject

相关问题