参考地址:springboot快速搭建web项目
<dependency>
<groupId>org.apache.shirogroupId>
<artifactId>shiro-springartifactId>
<version>1.4.0version>
dependency>
/**
* 自定义Realm 继承AuthorizingRealm
*/
public class UserRealm extends AuthorizingRealm {
@Autowired
UserService userService;
Logger logger = LoggerFactory.getLogger(UserRealm.class);
/**
* 授权
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
logger.info("执行了一次授权");
User user = (User) principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//动态授权
String role = user.getRole();
Optional<String> role1 = Optional.ofNullable(role);
role1.ifPresent(data->{
String[] split = data.split(";");
for (String r : split) {
if ("".equals(r)) continue;
info.addStringPermission(r);
}
});
return info;
}
/**
* 认证
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
logger.info("执行了一次认证");
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
//根据用户名获取密码
User user = userService.getUser(token.getUsername());
if (null==user) {//用户不存在
return null;//抛出UnknownAccountException 异常
}
return new SimpleAuthenticationInfo(user,user.getPassword(),getName());
}
}
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean filterFactoryBean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager);
/**
* 添加shiro内置过滤器
* anon 无需认证就可访问
* authc 必须认证才能访问
* user 必须拥有 记住我 功能才能访问
* perms 拥有对某个资源的权限才能访问
* role 拥有某个角色权限才能访问
*/
Map<String,String> filterMap = new LinkedHashMap();
filterMap.put("/*","authc");//对所有用户认证
filterMap.put("/user/toLogin","anon");//登陆页面无需认证
filterMap.put("/user/login/*","anon");//登陆验证无需认证
//必须拥有相应的权限才可以访问
filterMap.put("/user/add","perms[user:add]");
filterMap.put("/user/update","perms[user:update]");
bean.setFilterChainDefinitionMap(filterMap);
//未认证时跳转的页面
bean.setLoginUrl("/user/toLogin");
//未授权时跳转的页面
bean.setUnauthorizedUrl("/user/noPerms");
return bean;
}
@Bean
public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//安全管理器关联userRealm
securityManager.setRealm(userRealm);
return securityManager;
}
/**
* 身份验证
* @return
*/
@Bean
public UserRealm userRealm(){
UserRealm userRealm = new UserRealm();
return userRealm;
}
}
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>toLogintitle>
head>
<body>
<form action="/user/login/login">
<p>用户名:<input name="name" type="text">p>
<p>密码:<input name="password" type="password">p>
<p style="color: red" th:text="${msg}">p>
<p><button type="submit">提交button> p>
form>
body>
html>
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>indextitle>
head>
<body>
<h2>首页h2>
<p> <a th:href="@{/user/add}">adda> <a th:href="@{/user/update}">updatea> p>
<p> <a th:href="@{/user/logout}">退出a> p>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>addtitle>
head>
<body>
<h2>add pageh2>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>updatetitle>
head>
<body>
<h2>update pageh2>
body>
html>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>noPermstitle>
head>
<body>
<h2>无权限!h2>
body>
html>
<dependency>
<groupId>com.github.theborakompanionigroupId>
<artifactId>thymeleaf-extras-shiroartifactId>
<version>2.0.0version>
dependency>
/**
* 整合shiro-thymelea
* 在前端页面也可以用shiro权限
* @return
*/
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
注:添加shiro命名空间
DOCTYPE html>
<html lang="en"
xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<h2>首页h2>
<p>
<div shiro:hasPermission="user:add">
<a th:href="@{/user/add}">adda>
div>
<div shiro:hasPermission="user:update">
<a th:href="@{/user/update}">updatea>
div>
p>
<p> <a th:href="@{/user/logout}">退出a> p>
body>
html>
/**
* 加密适配器
* @return
*/
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
//散列算法:MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512等。
hashedCredentialsMatcher.setHashAlgorithmName("MD5");
//散列的次数,默认1次, 设置两次相当于 md5(md5(""));
hashedCredentialsMatcher.setHashIterations(1);
return hashedCredentialsMatcher;
// MD5加密【Salt盐值(用户名) 】
// SimpleHash simpleHash = new SimpleHash("md5",password,Salt,1);
// String NewPassword = simpleHash.toString();
}
/**
* 身份验证
* @return
*/
@Bean
public UserRealm userRealm(HashedCredentialsMatcher hashedCredentialsMatcher){
UserRealm userRealm = new UserRealm();
//userRealm设置加密适配器
userRealm.setCredentialsMatcher(hashedCredentialsMatcher);
return userRealm;
}
/**
* 认证
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
logger.info("执行了一次认证");
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
//根据用户名获取密码
User user = userService.getUser(token.getUsername());
if (null==user) {//用户不存在
return null;//抛出UnknownAccountException 异常
}
//密码验证 shiro做~不用我们匹配
Object principal = user;//认证的实体信息,可以是userName也可以是user对象
String credentials = user.getPassword(); //验证的密码
String salt = user.getName();//mds加密盐值
String realmName = getName();//当前realm对象的name
return new SimpleAuthenticationInfo(principal,credentials, ByteSource.Util.bytes(salt),realmName);
}
/**
* 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions)
* 需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
* 配置以下两个bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)即可实现此功能
* @return
*/
@Bean
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
/**
* 开启aop注解支持
* @param defaultWebSecurityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager defaultWebSecurityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(defaultWebSecurityManager);
return authorizationAttributeSourceAdvisor;
}
filterMap.put("/user/add","perms[user:add]");
filterMap.put("/user/update","perms[user:update]");
package com.wu.shiro.config;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 无权限异常处理
*/
@ControllerAdvice
public class NoPermissionException {
Logger log = LoggerFactory.getLogger(NoPermissionException.class);
@ResponseBody
@ExceptionHandler(UnauthorizedException.class)
public String handleShiroException(Exception e) {
log.info("该操作无权限");
return "无权限";
}
@ResponseBody
@ExceptionHandler(AuthorizationException.class)
public String AuthorizationException(Exception e) {
log.info("权限认证失败");
return "权限认证失败";
}
}
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
UserService userService;
@RequestMapping("/toLogin")
public String toLogin(){
return "loginPage";
}
@RequestMapping("/login/login")
public String login(User user,Model model){
try {
//获取当前用户
Subject subject = SecurityUtils.getSubject();
//封装用户的登录token
UsernamePasswordToken token = new UsernamePasswordToken(user.getName(),user.getPassword());
//登录
subject.login(token);
return "index";
}catch (UnknownAccountException unknownAccount){
model.addAttribute("msg","用户名不存在!");
return "loginPage";
}catch (IncorrectCredentialsException Incorrect){
model.addAttribute("msg","密码错误!");
return "loginPage";
}
}
@RequestMapping("/logout")
public String logout(){
//获取当前用户
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "loginPage";
}
@RequiresPermissions("user:add")
@RequestMapping("/add")
public String add(){
return "user/add";
}
@RequiresPermissions("user:update")
@RequestMapping("/update")
public String update(){
return "user/update";
}
@RequestMapping("/noPerms")
public String noPerms(){
return "noPerms";
}
}