首先我们要保证导入的包正确,shiro-spring版本过高会导致某些类比如ShiroFilterFactoryBean找不到,我参照了网上的版本,供大家借鉴
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
确保导包完成后,新建一个config包,在config里新建UserRealm和ShiroConfig两个类,在Realm中需要继承AuthorizingRealm类
public class UserRealm extends AuthorizingRealm {
//授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了授权");
return null;
}
//认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行了认证");
retrun null;
}
紧接着,在ShiroConfig中执行如下步骤,顺序是从下至上
@Configuration
public class ShiroConfig {
@Bean//第三步
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager);
//anon 无需认证即可访问
//authc 必须认证才可访问
//user 记住我功能才能访问
// perms 拥有对某个资源的权限才能访问
//role:拥有某个角色权限才能访问
Map<String, String> filterMap = new LinkedHashMap<>();
// filterMap.put("/user/add", "authc");
// filterMap.put("/user/update", "authc");
filterMap.put("/user/*", "authc");
bean.setFilterChainDefinitionMap(filterMap);
//设置登录的请求
bean.setLoginUrl("/toLogin");
return bean;
}
@Bean(name = "securityManager") //第二步
public DefaultWebSecurityManager deDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(userRealm);
return securityManager;
}
//创建realm对象,需要自定义类 :第一步
@Bean
public UserRealm userRealm() {
return new UserRealm();
}
}
在templates里新建hello页面和login页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>首页</h1>
<a th:href="@{/user/add}">add</a>
<a th:href="@{/user/update}">update</a>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p th:text="${msg}" style="color: red"></p>
<form th:action="@{/login}">
<p>用户名: <input type="text" name="username"></p>
<p>密码:<input type="text" name="password"></p>
<p><input type="submit" value="登录"></p>
</form>
</body>
</html>
此时进入首页点add和update会直接被拦截跳到login页面,之所以会跳到login页面是因为在ShiroConfig 里面设置了一个 bean.setLoginUrl("/toLogin");
我们可以在controller层里面进行账号密码判断
@Controller
public class MyController {
@RequestMapping("/hello")
public String index() {
return "hello";
}
@RequestMapping("/user/add")
public String add() {
return "user/add";
}
@RequestMapping("/user/update")
public String update() {
return "user/update";
}
@RequestMapping("/toLogin")
public String toLogin() {
return "login";
}
@RequestMapping("/login")
public String login(String username, String password, Model model) {
//获取当前的用户
Subject subject = SecurityUtils.getSubject();
//封装用户的登录数据
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
//执行登录方法,没有异常就说明ok
try {
subject.login(token);
return "hello";
} catch (UnknownAccountException e) {//用户名不存在
model.addAttribute("msg", "用户名错误");
return "login";
} catch (IncorrectCredentialsException e) { //密码不存在
model.addAttribute("msg", "密码错误");
return "login";
}
}
}
此时我们在UserRealm进行修改,伪造账号密码
public class UserRealm extends AuthorizingRealm {
//授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了授权");
return null;
}
//认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行了认证");
//伪造账号密码
String name = "root";
String password = "123456";
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
if (!userToken.getUsername().equals(name)) {
return null; //抛出异常 UnknownAccountException
}
//密码认证,shiro做的
return new SimpleAuthenticationInfo("",password,"");
}
}
结构如图所示
设置账号密码为root;123456,输入错误的账号或者密码会给出相应的提示,账号密码全部正确则会跳转到hello页面中,shiro的简单授权入门完成!