当(在Spring Security / MVC中)对页面的访问被拒绝时,由于用户没有足够的权限(虽然他经过身份验证),我需要通过显示登录页面提供以另一个用户身份登录(而不是显示403访问被拒绝页面的标准行为。)
我可以写一个AccessDeniedHandler
,重定向到登录页面。但是当Spring Security发现有另外一个用户登录时会如何反应?当新用户成功通过身份验证后,我可以以某种方式注销旧用户吗?
答案 0 :(得分:2)
我已经尝试在已有其他用户登录时登录新用户。它可以正常工作 - 无需注销第一个用户。他的授权被新的授权所取代。这是我自己问题的简单答案。
如果有人感兴趣,如果访问被拒绝,如何转发登录页面 - 这是我的解决方案:
首先定义一个自定义RequestCache:
@Component("myRequestCache")
public class MyRequestCache extends HttpSessionRequestCache {
public MyRequestCache() {
super();
}
}
其次定义自定义AccessDeniedHandler:
@Component("myAccessDeniedHandler")
public class MyAccessDeniedHandler implements AccessDeniedHandler {
@Autowired
@Qualifier("myRequestCache")
private RequestCache myRequestCache;
public MyAccessDeniedHandler() {
}
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exc)
throws IOException, ServletException {
if (!response.isCommitted()) {
//Save Target-Request
shopRequestCache.saveRequest(request, response);
//Forward to the login page
request.getRequestDispatcher("/loginPage").forward(request, response);
}
}
}
第三步将这两个配置为Spring Security:
@Configuration
@EnableWebSecurity
public class myConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("myRequestCache")
RequestCache myRequestCache;
@Autowired
@Qualifier("myAccessDeniedHandler")
AccessDeniedHandler myAccessDeniedHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestCache()
.requestCache(myRequestCache)
.and()
.exceptionHandling()
.accessDeniedHandler(myAccessDeniedHandler)
}
}
这里发生了什么?
MyAccessDeniedHandler
转发到AccessDeniedException
登录页面。由于这个转发是由这个自编程类调用的,而不是由过滤器链中的Spring调用,我们必须告诉spring,目标请求是什么 - 在成功验证后必须重定向的位置。我们通过RequestCache
进行此操作。
答案 1 :(得分:0)
如果您要退出旧用户,我建议您使用SessionRegistry
(http://docs.spring.io/spring-security/site/docs/current/apidocs/org/springframework/security/core/session/SessionRegistry.html)
一些提示:
在Spring配置类
中@Configuration
class MyConfiguration{
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
}
在AccessDeniedHandler
:
@Autowired
private SessionRegistry sessionRegistry;
....
List<SessionInformation> sessionInformations = sessionRegistry.getAllSessions("an-user", false);
for(SessionInformation session: sessionInformations) {
session.expireNow();
}
答案 2 :(得分:-1)
您可以在spring security xml
文件中添加以下标记。
<http auto-config="true" use-expressions="true">
<access-denied-handler error-page="/accessDenied" />
<intercept-url pattern="/publicIndex1" access="isAnonymous()"/>
<intercept-url pattern="/index1" access="isAnonymous()"/>
<!-- Restrict URLs based on role -->
<intercept-url pattern="/#/publicIndex" access="isAnonymous()" />
<form-login
login-page="/publicIndex1"
always-use-default-target="false"
default-target-url="/index"
authentication-failure-url="/publicIndex1"
username-parameter="username"
password-parameter="password" />
<logout logout-success-url="/index1"
delete-cookies="JSESSIONID"
logout-url="/logout"
invalidate-session="true" />
</http>
在你的弹簧控制器中。
@RequestMapping(value = "/accessDenied", method = RequestMethod.GET)
public ModelAndView accessDenied() {
System.out.println("access denied page call");
return new ModelAndView("accessDenied");
}
@RequestMapping(value = "/#/publicIndex", method = RequestMethod.GET)
public ModelAndView login(@RequestParam(value = "error", required = false) String error,
@RequestParam(value = "logout", required = false) String logout) {
System.out.println("inside /#/public index");
ModelAndView model = new ModelAndView();
if (error != null) {
model.addObject("error", "Invalid username and password!");
}
System.out.println("**********************" + error);
if (logout != null) {
model.addObject("msg", "You've been logged out successfully.");
}
model.setViewName("publicIndex");
return model;
}
@RequestMapping(value = "/logout", method = RequestMethod.GET)
public String logout1() {
System.out.println();
User user1 = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return userService.addUserOffline(user1.getUserId());
}
@RequestMapping(value = "/index", method = RequestMethod.GET)
public ModelAndView index() {
System.out.println("Redirect Controller Call");
User user = new User();
try {
user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
} catch (Exception e) {
return new ModelAndView("publicIndex1");
}
long userId = user.getUserId();
userService.addLastLoginDate(userId);
System.out.println("user id==" + userId);
return new ModelAndView("index");
}
@RequestMapping(value = "/index1", method = RequestMethod.GET)
public ModelAndView index1() {
System.out.println("inside logout index1");
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (!(auth instanceof AnonymousAuthenticationToken)) {
return new ModelAndView("/index");
} else {
return new ModelAndView("index1");
}
}