shrio QuickStart
Shrio三大对象:
springboot整合shrio
登录拦截认证
创建项目时勾选web,导入依赖:
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.5.3</version> </dependency>
自定义一个登录页面,shrio不同于spring-secruity给我做好了登录页面,我们需要自定义
login.html代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登录页面</title> </head> <body> <p th:text="${msg}" style="color:red;"></p> <form th:action="@{/Login}" > <div>用户名:<input type="text" name="username" placeholder="username"></div> <div>密码:<input type="password" name="password" placeholder="password"></div> <button>登录</button> </form> </body> </html>
controller代码 测试是否成功拦截并跳转到登录页面
package com.lian.controller; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.IncorrectCredentialsException; import org.apache.shiro.authc.UnknownAccountException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class MycController { @RequestMapping("/user/add") public String add(){ return "add"; } @RequestMapping("/user/update") public String UPDATE(){ return "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); try{ subject.login(token); return "index"; } catch (UnknownAccountException e){ model.addAttribute("msg","用户名错误"); return "login"; } catch (IncorrectCredentialsException e){ model.addAttribute("msg","密码错误"); return "login"; } } }
登录拦截并认证配置代码
注意shrio自己帮我们进行了密码的认证,只需要传入password到类SimpleAuthenticationInfo的构造方法中即可
package com.lian.config; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; public class UserRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行了=>授权doGetAuthorizationInfo"); return null; } @Override//用户登录后要认证其拥有哪些权限,先伪造一个用户名和密码测试一下 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("执行力=>认证doGetAuthenticationInfo"); String username="lian"; String password="123"; UsernamePasswordToken userToken=(UsernamePasswordToken)token; if(!userToken.getUsername().equals(username)){//前端传入的用户名和这里设置的不同 //不同,抛出异常 return null;// } return new SimpleAuthenticationInfo("",password,""); } }
启动主启动类同时在网页进行测试
授权
用户在提交登录表单瞬间后台要判断用户拥有哪些权限,我们在数据库中新增 个字段perms代表用户权限,同时注意如果用户没有某个子页面的权限,那么在用户登录成功后就不用展示那个页面对应的超链接了,因此我们也需要整合thymeleaf和shrio
检查一下环境
public class UserRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行了=>授权doGetAuthorizationInfo"); return null; } @Override//用户登录后要认证其拥有哪些权限,先伪造一个用户名和密码测试一下代码有没有其他问题 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("执行力=>认证doGetAuthenticationInfo"); String username="lian"; String password="123"; UsernamePasswordToken userToken=(UsernamePasswordToken)token; if(!userToken.getUsername().equals(username)){//前端传入的用户名和这里设置的不同 //不同,抛出异常 return null;// } return new SimpleAuthenticationInfo("",password,""); } }
思路:shiro登录认证的根本是先根据用户名查询出用户的账号密码等信息保存到
SimpleAuthenticationInfo中,试图登录的用户信息保存到UsernamePasswordToken中,
最后通过subject调用login方法实现登录信息的匹配对比。
1.创建项目时勾选web,导入thymeleaf依赖:
2.查看源码查看shrio中要授权用户的方法应该如何写
测试代码:
UserRealm.java
package com.lian.config; import com.lian.pojo.User; import com.lian.service.UserService; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.session.Session; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.Subject; import org.springframework.beans.factory.annotation.Autowired; public class UserRealm extends AuthorizingRealm { @Autowired UserService userService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行了=>授权doGetAuthorizationInfo"); SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(); info.addStringPermission("user:add"); //拿到当前登录的用户的对象 Subject subject= SecurityUtils.getSubject(); User currrentUser= (User) subject.getPrincipal();//拿到user对象 //设置当前用户的权限 info.addStringPermission(currrentUser.getPerms()); return info; } @Override//用户登录后要认证其拥有哪些权限,先伪造一个用户名和密码测试一下 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("执行力=>认证doGetAuthenticationInfo"); //token令牌 UsernamePasswordToken userToken=(UsernamePasswordToken)token; //连接真实数据库,比较数据库的用户名和前端用户名是否一致 User user= userService.queryUserByName(userToken.getUsername()); // ,而shiro登录认证的根本是先根据用户名查询出用户的账号密码等信息保存到 // SimpleAuthenticationInfo中,试图登录的用户信息保存到UsernamePasswordToken中, // 最后通过subject调用login方法实现登录信息的匹配对比, if(user==null){//前端传入的用户名和这里设置的不同 System.out.println("用户不存在!"); return null;//报错 } Subject currentSubject=SecurityUtils.getSubject(); Session session=currentSubject.getSession(); session.setAttribute("loginUser",user); return new SimpleAuthenticationInfo(user,user.getPwd(),""); } }
ShrioConfig
package com.lian.config; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.LinkedHashMap; import java.util.Map; @Configuration public class ShrioConfig { @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean(); //设置安全管理器 bean.setSecurityManager(defaultWebSecurityManager); /* * 添加shrio的内置过滤器 * anon:无需认证可以访问 * anthc:必须认证才能访问 * user:必须拥有记住我功能才能用 * perms:拥有对某某个资源的权限才能访问 * role:拥有某个角色权限才能访问*/ //拦截 Map<String,String> filterMap=new LinkedHashMap<>(); //授权,正常情况下,没有授权会跳转到未授权的页面 filterMap.put("/user/add","perms[user:add"); filterMap.put("/user/add","perms[user:update"); filterMap.put("/user/*","authc"); bean.setFilterChainDefinitionMap(filterMap); //设置登录的请求 bean.setLoginUrl("/toLogin"); //未授权的页面,表明在用户点击某个a连接时发现未经认证,要走下面这个controller方法走 bean.setUnauthorizedUrl("/noauth"); return bean; } @Bean(name = "securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){ DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager(); //关联userRealm securityManager.setRealm(userRealm); return securityManager; } @Bean(name = "userRealm") //创建realm对象,需要自定义类 public UserRealm realm(){ return new UserRealm(); } }
前端thymeleaf和shiro整合