依赖导入
<!--shiro-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
自定义realm
doGetAuthenticationInfo()
方法:用来验证当前登录的用户,获取认证信息
doGetAuthorizationInfo()
方法:用来为当前登陆成功的用户授予权限和角色
public class MyReam extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 用来为当前登陆成功的用户授予权限和角色
*
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取用户名
String username = (String) principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
//给用户设置角色,t_role获取
authorizationInfo.setRoles((Set<String>) userService.getRoles(username));
//给用户设置权限,t_permission获取
authorizationInfo.setStringPermissions(userService.getPermissions(username));
return authorizationInfo;
}
/**
* 用来验证当前登录的用户,获取认证信息
*
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//根据token获取username
String username = (String) authenticationToken.getPrincipal();
//根据用户名从数据库中获取该用户信息
User user = userService.getByUsername(username);
if (null != user) {
//存入session中
SecurityUtils.getSubject().getSession().setAttribute("user", user);
//传入用户名和密码进行身份认证,并返回认证信息
AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), "myRealm");
return authenticationInfo;
} else {
return null;
}
}
}
注入Spring
配置自定义realm
@Configuration
@Slf4j
public class ShiroConfig {
/**
* 注入MyReam
* @return MyReam
*/
@Bean
public MyReam myAuthRealm() {
MyReam myReam = new MyReam();
log.info("myRealm注册完成============");
return myReam;
}
}
配置securityManager
/**
* 注入安全管理器
* @return
*/
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(myAuthRealm());
log.info("securityManager注册完成");
return securityManager;
}
配置 Shiro
过滤器
/**
* 配置shiro过滤器
* @param securityManager
* @return
*/
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
//定义shiroFactoryBean
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置自定义的securityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
//设置默认登陆的url,身份认证失败会访问该url
shiroFilterFactoryBean.setLoginUrl("/user/toLogin");
//设置成功登录之后跳转的链接
shiroFilterFactoryBean.setSuccessUrl("/user/success");
//设置未授权界面,权限认证失败会访问
shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
//有序进行拦截
Map<String, String> filterChainMap = new LinkedHashMap<>();
//配置可以匿名访问的资源,如静态css,js,anno表示放行
filterChainMap.put("/css/**","anon");
filterChainMap.put("/imgs/**","anon");
filterChainMap.put("/js/**","anon");
filterChainMap.put("/swagger-*/**","anon");
filterChainMap.put("/swagger-ui.html/**","anon");
//放行登录接口
filterChainMap.put("/user/login","anon");
// “/user/admin” 开头的需要身份认证,authc表示要身份认证
filterChainMap.put("/user/admin*", "authc");
// “/user/student” 开头的需要角色认证,是“admin”才允许
filterChainMap.put("/user/student*/**", "roles[admin]");
// “/user/teacher” 开头的需要权限认证,是“user:create”才允许
filterChainMap.put("/user/teacher*/**", "perms[\"user:create\"]");
// 配置logout过滤器接口(可以不存在),执行该接口会销毁当前session,需要重新登录。
// @TODO filterChainMap.put("/logout", "logout"); shiro的这个接口有问题,不会跳转登录页面,我是自己实现
// 设置shiroFilterFactoryBean的FilterChainDefinitionMap
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
log.info("====shiroFilterFactoryBean注册完成====");
return shiroFilterFactoryBean;
}
登录接口实现
/**
* 用户登录接口
* @param user user
* @param request request
* @return string
*/
@PostMapping("/login")
public String login(User user, HttpServletRequest request) {
// 根据用户名和密码创建token
UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
// 获取subject认证主体
Subject subject = SecurityUtils.getSubject();
try{
// 开始认证,这一步会跳到我们自定义的realm中
subject.login(token);
request.getSession().setAttribute("user", user);
return "success";
}catch(Exception e){
e.printStackTrace();
return "login";
}
}
其他接口实现
@Controller
@RequestMapping("/user")
@ApiOperation("用户")
public class UserController {
/**
* 注销当前用户
* @return
*/
@RequestMapping("/logout")
public String logout() {
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "login";
}
/**
* 跳转登录页面
* @return
*/
@RequestMapping("/toLogin")
public String toLogin() {
return "login";
}
/**
* 用户登录接口
* @param user user
* @param request request
* @return string
*/
@PostMapping("/login")
public String login(User user, HttpServletRequest request) {
// 根据用户名和密码创建token
UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
// 获取subject认证主体
Subject subject = SecurityUtils.getSubject();
try{
// 开始认证,这一步会跳到我们自定义的realm中
subject.login(token);
request.getSession().setAttribute("user", user);
return "success";
}catch(Exception e){
e.printStackTrace();
return "login";
}
}
/**
* 身份认证测试接口
* @param request
* @return
*/
@GetMapping("/admin")
public String admin(HttpServletRequest request) {
Object user = request.getSession().getAttribute("user");
return "success";
}
/**
* 角色认证测试接口
* @param request
* @return
*/
@GetMapping("/student")
public String student(HttpServletRequest request) {
return "success";
}
/**
* 权限认证测试接口
* @param request
* @return
*/
@GetMapping("/teacher")
public String teacher(HttpServletRequest request) {
return "success";
}
@RequestMapping("/success")
public String success() {
return "success";
}
}
新建模板文件
登录页面
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
</head>
<body>
<form action="/user/login" method="post">
用户名:<input type="text" name="username"/><br>
密码:<input type="password" name="password"/><br>
<button type="submit">登录</button>
</form>
</body>
</html>
登录成功页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录成功</title>
</head>
<body>
恭喜你,登录成功
</body>
</html>
最后访问相应接口测试即可。