要将SpringMVC和Shiro集成起来,需要进行以下步骤:
1. 导入相关依赖
在项目的pom.xml文件中,需要添加spring-boot-starter-web、shiro-spring、shiro-core和thymeleaf等相关依赖。具体依赖版本可以自行选择,这里我给出一个示例:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
2. 配置Shiro和SpringMVC
在Spring Boot应用程序中,可以在application.properties文件中配置Shiro和SpringMVC:
# Shiro配置
shiro.loginUrl = /login
shiro.successUrl = /index
shiro.unauthorizedUrl = /unauthorized
# SpringMVC配置
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.html
3. 编写Shiro配置类
Shiro的配置需要一个ShiroConfig类,通常继承自ShiroWebMvcConfigurerAdapter,这样可以将Shiro拦截器和SpringMVC的拦截器进行集成。
@Configuration
public class ShiroConfig {
@Autowired
private Environment env;
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager);
shiroFilter.setLoginUrl(env.getProperty("shiro.loginUrl"));
shiroFilter.setUnauthorizedUrl(env.getProperty("shiro.unauthorizedUrl"));
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/static/**", "anon");
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/**", "authc");
shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilter;
}
@Bean
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(shiroRealm());
return securityManager;
}
@Bean
public ShiroRealm shiroRealm() {
ShiroRealm shiroRealm = new ShiroRealm();
return shiroRealm;
}
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
}
4. 编写ShiroRealm类
ShiroRealm是实现Shiro用户身份验证和授权的核心,需要继承AuthorizingRealm类,实现doGetAuthenticationInfo和doGetAuthorizationInfo方法。
public class ShiroRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// 授权
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
User user = (User) principals.getPrimaryPrincipal();
authorizationInfo.setRoles(userService.getUserRoles(user.getUsername()));
authorizationInfo.setStringPermissions(userService.getUserPermissions(user.getUsername()));
return authorizationInfo;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
// 身份验证
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
String username = upToken.getUsername();
User user = userService.getUserByUsername(username);
if (user == null) {
throw new UnknownAccountException("用户不存在!");
}
return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
}
}
5. 编写用户服务类
用户服务类是指封装用户信息并提供相关服务的类,这里我假设UserService类已经完成并可用。
6. 编写登录控制器
登录控制器负责处理用户登录请求和跳转,登录表单也应该在此处处理。成功或失败后需要处理相应的逻辑。
@Controller
public class LoginController {
@RequestMapping("/login")
public String login(HttpServletRequest request) {
String exceptionClassName = (String) request.getAttribute("shiroLoginFailure");
String error = null;
if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
error = "用户名/密码错误";
} else if (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
error = "用户名/密码错误";
} else if (AuthenticationException.class.getName().equals(exceptionClassName)) {
error = "无效的用户名/密码";
} else if (exceptionClassName != null) {
error = "其他错误:" + exceptionClassName;
}
request.setAttribute("error", error);
return "login";
}
@RequestMapping("/")
public String index() {
return "index";
}
@RequestMapping("/unauthorized")
public String unauthorized() {
return "unauthorized";
}
@RequestMapping("/logout")
public String logout() {
Subject subject = SecurityUtils.getSubject();
if (subject != null) {
subject.logout();
}
return "redirect:/login";
}
}
以上就是SpringMVC集成Shiro登录失败处理的完整攻略,具体过程还需要根据项目实际情况进行调整。以下是两个示例:
示例一:登录失败后跳转到同一页面,并提示错误信息
需要在控制器方法中添加shiroLoginFailure属性,并根据登录验证不通过的情况进行错误信息的提示:
@RequestMapping("/login")
public String login(HttpServletRequest request) {
String exceptionClassName = (String) request.getAttribute("shiroLoginFailure");
String error = null;
if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
error = "用户名/密码错误";
} else if (IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
error = "用户名/密码错误";
} else if (AuthenticationException.class.getName().equals(exceptionClassName)) {
error = "无效的用户名/密码";
} else if (exceptionClassName != null) {
error = "其他错误:" + exceptionClassName;
}
request.setAttribute("error", error);
return "login";
}
这样,在登录验证不通过的情况下,会自动跳转回登录页面,并提示相应的错误信息。
示例二:登录失败后跳转到不同页面,并提示错误信息
在控制器中添加ShiroFilterFactoryBean的unauthorizedUrl属性,将其指向不允许访问的页面即可。这样,在用户登录验证不通过或者没有权限的时候,会跳转到指定的页面。
@Bean
public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
shiroFilter.setSecurityManager(securityManager);
shiroFilter.setLoginUrl(env.getProperty("shiro.loginUrl"));
shiroFilter.setUnauthorizedUrl(env.getProperty("shiro.unauthorizedUrl"));
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
filterChainDefinitionMap.put("/static/**", "anon");
filterChainDefinitionMap.put("/logout", "logout");
filterChainDefinitionMap.put("/admin", "roles[admin]");
filterChainDefinitionMap.put("/**", "authc");
shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilter;
}
@RequestMapping("/unauthorized")
public String unauthorized() {
return "unauthorized";
}
这样,在用户访问不允许访问的页面时,会自动跳转到unauthorized页面,并提示相应的错误信息。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:springmvc集成shiro登录失败处理操作 - Python技术站