当(在Spring Security/MVC中)页面访问被拒绝时,由于用户没有足够的权限(尽管他已通过身份验证),我需要通过显示登录页面(而不是显示403拒绝访问页面的标准行为)提供作为另一个用户登录
我可以编写一个AccessDeniedHandler
,重定向到登录页面。但是,当Spring Security发现有另一个用户登录时,它会做出怎样的反应?当新用户已成功通过身份验证时,我能否以某种方式注销旧用户?
您可以在spring securityxml
文件中添加以下标记。
<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>
在spring控制器中。
@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");
}
}
如果你想注销旧用户,我建议使用Session注册表
(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();
}
我尝试在已有其他用户登录时登录新用户。它可以工作——不需要第一个用户注销。他的授权被新的授权所取代。这是我自己问题的简单答案。
如果有人感兴趣,如何在访问被拒绝的情况下转发到登录页面-以下是我的解决方案:
首先定义自定义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
myRequestCache.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)
}
}
这里发生了什么
如果出现AccessDeniedException
,则MyAccessDeniedHandler
将转发到登录页面。由于这个转发是由这个自编程类调用的,而不是由过滤器链中的Spring调用的,所以我们必须告诉Spring,目标请求是什么——成功身份验证后,它必须重定向到哪里。这是通过RequestCache
实现的。
记录器文件中的日志- org.springframework.Security.Access.event.loggerlistener-安全授权失败,原因是:org.springframework.Security.Access.accessdeniedexception:访问被拒绝;通过身份验证的主体:org.springframework.security.authentication.ano
我现在一直在努力使用我的登录页面来让组件呈现Loggedin组件。我的前端是Reactjs,后端是NodeJS。我对nodejs、expression和react都是新手。 在loginform组件上,我使用fetch进行了一次post,它将用户名和密码传递给后端的相应endpoint。没问题。在后端,它读取我存储用户(不使用任何数据库)的jsonfile来查找匹配项,如果用户名和密码都匹配,则它
我在Laravel框架中的HomeController.php中有一段代码,但是我无法访问它重定向到登录页面的索引/主页。我犯了什么大错?
我使用的是Spring Security 4.1.1,但我遇到了一个问题:我试图访问URL,应用程序会重定向到登录页面。到现在为止,一直都还不错。 但是,成功登录后,应用程序会再次将我重定向到登录页面,并且不会创建任何会话,因此即使尝试直接访问URL(在URL栏中键入),应用程序也会重定向到登录页面。 有一些URL我必须要求登录才能访问它们。其他的,我可以访问无需身份验证。这些我不需要验证的URL
问题内容: 我正在做一个简单的论坛,由一系列论坛组成,每个论坛分别代表首页,主题,postitit,登录名和用户列表页面。在某些页面上,当用户未登录时会出现一个链接。 我想要实现的是在登录后触发重定向(在RequestDispatcher上使用forward()),以便浏览器返回到用户在单击登录链接之前所在的页面。为此,我看到了两种解决方案。 第一种解决方案是使用带有登录按钮的HTML 和一个不可
我在Laravel5.2中使用了php artisan函数。 我想重定向的客人登录页面,若客人点击链接,只有用户并没有客人。 我想在登录后将用户重定向到后面的页面。 我怎么能这么做?请详细展示一些文件名示例。 ///////编辑 路线 控制器 Kernel.php