第一步:导包
<!-- shiro整合spring--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency> <!-- shiro整合thymeleaf --> <dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.0.0</version> </dependency>
<!-- 日志--> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <!-- thymeleaf--> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> </dependency> <!--使用Spring Boot和Thymeleaf,并且需要在视图中格式化Java 8 Date&Time对象,下一步就是将方言添加到模板引擎--> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-java8time</artifactId> </dependency> <!-- 驱动--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!-- 数据源--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.6</version> </dependency> <!-- mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.2.2</version> </dependency> <!-- web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- 构造函数--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--连接数据库--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <!-- 测试--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
第二步:Realm和ShiroConfig
Realm:
public class UserRealm extends AuthorizingRealm { @Autowired UserService userService; //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.out.println("执行了=》授权"); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //当前登录对象 Subject subject = SecurityUtils.getSubject(); User currentUser = (User)subject.getPrincipal();//是getPrincipal而不是getPrincipals //设置当前用户权限 info.addStringPermission(currentUser.getPerms()); return info; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("执行了==》认证"); //点击登录就会走这个方法,然后点击其他页面的时候走上边的授权方法 //用户名,密码 数据库中去取 UsernamePasswordToken userToken = (UsernamePasswordToken) token; //链接真是数据库 User user = userService.getUserByName(userToken.getUsername()); System.out.println(user); //用户认证 if (user==null){ System.out.println("账号验证!"); return null;//抛出异常UnknownAccountException e } //登陆成功 System.out.println("账号验证通过"); //当前登陆对象 Subject currentSubject = SecurityUtils.getSubject(); Session session = currentSubject.getSession(); session.setAttribute("loginUser",user); //密码认证 shiro自动执行 System.out.println("密码验证"); return new SimpleAuthenticationInfo(user,user.getPassword(),""); }
ShiroConfig:
@Configuration public class ShiroConfig { //创建realm对象(授权认证的对象),需要自定义:1 @Bean(name = "userRealm") public UserRealm userRealm() { UserRealm userRealm = new UserRealm(); return userRealm; } //DefaultWebSecurityManager:2 @Bean(name = "securityManager") public DefaultWebSecurityManager getdefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); //关联realm securityManager.setRealm(userRealm); return securityManager; } // ShiroFilterFactoryBean:3 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); //设置安全管理器 shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager); //添加shiro的内置过滤器 /* anon:无需认证就可以访问 authc:必须认证了才能访问 user:必须有 记住我 功能才能访问 perms:拥有了对某个资源的权限访问才能访问 role:拥有了某个角色才能访问 */ //登录拦截 Map<String,String> filterMap = new LinkedHashMap<>(); //授权,正常的情况下,没有授权会跳转到未授权页面 filterMap.put("/user/add","perms[user:add]"); filterMap.put("/user/update","perms[user:update]"); filterMap.put("/user/*","authc");//必须认证了才能访问 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap); //设置登陆的请求,请求被拦截后的跳转界面 shiroFilterFactoryBean.setLoginUrl("/toLogin"); //未授权页面 shiroFilterFactoryBean.setUnauthorizedUrl("/unauth"); return shiroFilterFactoryBean; } //整合ShiroDialect:用来整合shiro thymeleaf //实现shiro想要实现的前端页面显示 @Bean public ShiroDialect getShiroDialect() { return new ShiroDialect(); } }
Controller:
@Controller public class UserController { // @Autowired // private UserService userService; // @RequestMapping("/user") // public String user(){ // User user = userService.getUserById(1); // System.out.println(user); // return "select user succed!"; // } //用Model向前端页面传输 @RequestMapping({"/","/index"}) public String toIndex(Model model){ model.addAttribute("msg","hello shiro"); return "index"; } @RequestMapping("/user/add") public String add(){return "user/add";} @RequestMapping("/user/update") public String update(){return "user/update";} //shiro设定的登陆界面(默认界面) @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 { System.out.println("执行登陆的方法"); subject.login(token);//执行登陆的方法(走UserRealm的认证) System.out.println("登陆成功"); return "index";//登陆成功 }catch (UnknownAccountException e){ System.out.println("没有此用户"); model.addAttribute("msg","用户名错误"); return "login";//继续登录 }catch (IncorrectCredentialsException e){ System.out.println("密码错误"); model.addAttribute("msg","密码错误"); return "login";//继续登录 } } @RequestMapping("/unauth") @ResponseBody @ExceptionHandler(value = {UnauthorizedException.class}) public String unauthorized(){return "未经授权禁止访问!";}
后台处理流程:
1.首先前端页面走这里
@RequestMapping({"/","/index"}) public String toIndex(Model model){ model.addAttribute("msg","hello shiro"); return "index"; }
2.点击登陆之后,跳转到这个页面:
//前端登录界面输入账号密码之后到这儿处理 @RequestMapping("/login") public String login(String username,String password,Model model){ //获取当前用户 Subject subject = SecurityUtils.getSubject(); //封装用户的登陆数据 UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { System.out.println("执行登陆的方法"); subject.login(token);//执行登陆的方法(走UserRealm的认证) System.out.println("登陆成功"); return "index";//登陆成功 }catch (UnknownAccountException e){ System.out.println("没有此用户"); model.addAttribute("msg","用户名错误"); return "login";//继续登录 }catch (IncorrectCredentialsException e){ System.out.println("密码错误"); model.addAttribute("msg","密码错误"); return "login";//继续登录 } }
3.输入账号密码点击登录后:
subject.login(token);//执行登陆的方法(走UserRealm的认证)----》Realm的认证,如果有此用户继续验证密码是否正确,如果正确,显示下一个页面,如果不正确抛出异常,走这里------》
catch (IncorrectCredentialsException e){ System.out.println("密码错误"); model.addAttribute("msg","密码错误"); return "login";//继续登录 }
如果所查用户数据库中不存在,走这里-----》
catch (UnknownAccountException e){ System.out.println("没有此用户"); model.addAttribute("msg","用户名错误"); return "login";//继续登录