最近也被这个难题搞的我头都大了额。写下此篇文章献给自己和广大朋友。如果有不懂的地方可以加企鹅号询问哦。
企鹅号:2054861587,不一定会时时在,但如果有空的话就会给你回答
maven依赖:
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.2.5</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.2.5</version> </dependency>
项目下面新建Shiro配置类。
以下为配置类代码:
这里有个坑,也是这个坑让我头疼了好久,就是当你没有写自定义的ShiroRealm类时,下面代码会疯狂报错。
ps:亲,记得哦。ShiroRealm类的代码在后面。
@Configuration public class ShiroConfiguration { @Bean(name = "lifecycleBeanPostProcessor") public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } @Bean(name = "shiroRealm") @DependsOn("lifecycleBeanPostProcessor") public ShiroRealm shiroRealm() { ShiroRealm realm = new ShiroRealm(); return realm; } @Bean(name = "ehCacheManager") @DependsOn("lifecycleBeanPostProcessor") public EhCacheManager ehCacheManager() { EhCacheManager ehCacheManager = new EhCacheManager(); return ehCacheManager; } @Bean("securityManager") public DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(shiroRealm()); securityManager.setCacheManager(ehCacheManager());//用户授权/认证信息Cache, 采用EhCache 缓存 return securityManager; } @Bean(name = "shiroFilter") public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(securityManager()); System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"); Map<String, String> filterChainDefinitionManager = new LinkedHashMap<>(); filterChainDefinitionManager.put("/logout", "logout"); filterChainDefinitionManager.put("/user/**", "authc,roles[user]"); filterChainDefinitionManager.put("/shop/**", "authc,roles[shop]"); filterChainDefinitionManager.put("/admin/**", "authc,roles[admin]"); filterChainDefinitionManager.put("/login", "anon");//anon 可以理解为不拦截 filterChainDefinitionManager.put("/ajaxLogin", "anon");//anon 可以理解为不拦截 filterChainDefinitionManager.put("/static/**", "anon");//静态资源不拦截 //filterChainDefinitionManager.put("/**", "authc,roles[user]");//其他资源全部拦截 filterChainDefinitionManager.put("/**", "anon"); // filterChainDefinitionManager.put("/controller/MangerController", "anon"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionManager); shiroFilterFactoryBean.setLoginUrl("/login"); shiroFilterFactoryBean.setSuccessUrl("/"); shiroFilterFactoryBean.setUnauthorizedUrl("/403"); return shiroFilterFactoryBean; } @Bean @ConditionalOnBean public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator(); daap.setProxyTargetClass(true); return daap; } /** * 开启shiro aop注解支持 * 使用代理方式,所以需要开启代码支持 * * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) { AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor(); aasa.setSecurityManager(securityManager); return aasa; }
ShiroRealm类:
这里的User、role、Permission为实体类,实体类代码最下面贴出,mangerService为实现层,下面也会放出代码。
public class ShiroRealm extends AuthorizingRealm { private Logger logger=LoggerFactory.getLogger(ShiroRealm.class); @Autowired private MangerService mangerService; @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { logger.info("##################执行Shiro权限认证##################"); User user= (User) principalCollection.getPrimaryPrincipal(); if(user!=null){ SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(); //用户的角色集合 info.addRoles(user.getRolelist()); //用户的权限集合 info.addStringPermissions(user.getPerminslist()); return info; } return null; } /** * 登录认证 * @param authenticationToken * @return */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken token= (UsernamePasswordToken) authenticationToken; logger.info("验证当前SubJect时获取到的token为:"+token.toString()); User user=mangerService.getUser(token.getUsername()); System.out.println(token.getUsername()); if(user!=null){ //若存在,将此用户存放到登录认证info中,无需自己做密码对比,Shiro会为我们进行密码对比校验 List<Role> rlist = mangerService.findRoleByUid(user.getUS_ID());//获取用户角色 List<Permission> plist = mangerService.findPermissionByUid((user.getUS_ID()));//获取用户权限 List<String> roleStrlist=new ArrayList<String>();用户的角色集合 List<String> perminsStrlist=new ArrayList<String>();//用户的权限集合 for (Role role : rlist) { roleStrlist.add(role.getName()); } for (Permission permission : plist) { perminsStrlist.add(permission.getName()); } user.setRolelist(roleStrlist); user.setPerminslist(perminsStrlist); Session session = SecurityUtils.getSubject().getSession(); session.setAttribute("user", user);//成功则放入session //若存在,将此用户存放到登录认证info中,无需自己做密码对比,Shiro会为我们进行密码对比校验 return new SimpleAuthenticationInfo(user, user.getUS_PASS(), getName()); } return null; } }
mangerService代码如下,其余方法就不贴出了,只贴出上面ShiroRealm类调用的三个类:
public List<Role> findRoleByUid(String us_id) { return mdao.findRoleByUid(us_id); } public List<Permission> findPermissionByUid(String us_id) { return mdao.findPermissionByUid(us_id); } public User getUser(String username) { return mdao.getUser(username); }
mdao代码如下:
public User getUser(String username);
List<Role> findRoleByUid(String us_id); List<Permission> findPermissionByUid(String us_id);
都是最普通的代码,o(∩_∩)o 哈哈 下面上XML代码:
<select id="getUser" resultType="user" parameterType="String"> select us_id,us_name,us_name_kp,us_pass from bas_user where us_name=#{param1} </select> <select id="findRoleByUid" resultType="Role" parameterType="String"> select * from u_role where id=#{param1} </select> <select id="findPermissionByUid" resultType="Permission" parameterType="String"> select * from u_permission where id=#{param1} </select>
Controller层:
@RequestMapping(value = "/login") public String login(HttpServletRequest request, HttpServletResponse response,Model model) { response.setContentType("text/html;charset=utf-8"); String username = request.getParameter("username"); String password = request.getParameter("password"); UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password); Subject subject=SecurityUtils.getSubject(); try { logger.info("对用户["+username+"]开始进行登录验证...验证开始"); subject.login(usernamePasswordToken); logger.info("对用户[" + username + "]进行登录验证..验证通过"); } catch (UnknownAccountException e) { logger.info("对用户[" + username + "]进行登录验证..验证未通过,未知账户"); logger.info("未知帐号"); }catch (IncorrectCredentialsException ice){ logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证"); logger.info("密码不正确"); }catch(LockedAccountException lae){ logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证"); logger.info("帐户已锁定"); }catch (AuthenticationException e){ logger.info("用户名或密码不正确"); } User user= (User) subject.getPrincipal(); return "index"; }
博主承认上面的代码有点绕,如果实在不懂,欢迎提问,或者你直接照抄也木有问题。
表结构的兄弟不要着急,相信你们看了实体类代码后也会建表了,如果还是不明白,那就请继续往下面看,博主再说详细些。
public class User { private String US_ID; //用户ID private String US_NAME; //用户名 private String US_PASS; //密码 private List<String> rolelist; private List<String> perminslist; 以下省略N多的GET/SET/Tostring方法. }
Role实体类:
private String id; private String name;//角色名称 private String type;//角色类型
pemins实体类:
private String id; private String url;//url地址 private String name;//url描述
OK后台代码搞定了。
数据库表还不知道怎么建的同学,看着博主的 实体类。String或int 为数据库的数据类型,
user表当中没有rolelist、perminslist。只有用户ID、用户名、密码
user表当中没有rolelist、perminslist。只有用户ID、用户名、密码
user表当中没有rolelist、perminslist。只有用户ID、用户名、密码
重要的事情说三遍。
还不懂?那就举个例子咯:
pemins实体类举例。
private String id;
private String url;//url地址
private String name;//url描述
那么我们在数据库当中应该这么定义:
create table pemis(
id varchar(20),
url varchar(50),
name varchar(80)
)
那么pemins这个表我们就新建好了,有几个实体类就有几张表,亲。如果还不会,额去找你的数据库老师吧。
JSP页面调用:
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
放在最上面,不要问为啥,我就是要励志站在顶端的男人。
<shiro:authenticated>用户已经登录显示此内容<br/></shiro:authenticated><br/>
<shiro:hasRole name="manager">manager角色登录显示此内容<br/></shiro:hasRole>
<shiro:hasRole name="admin">admin角色登录显示此内容<br/></shiro:hasRole>
<shiro:hasRole name="normal">normal角色登录显示此内容<br/>
</shiro:hasRole><br/> <shiro:hasAnyRoles name="manager,admin">manager or admin 角色用户登录显示此内容<br/>
</shiro:hasAnyRoles><br/> <shiro:principal/>-显示当前登录用户名<br/><br/>
<shiro:hasPermission name="add">add权限用户显示此内容<br/>
</shiro:hasPermission> <shiro:hasPermission name="user:query">user:query权限用户显示此内容<br/>
</shiro:hasPermission>
<shiro:lacksPermission name="user:query">不具有user:query权限的用户显示此内容 <br/></shiro:lacksPermission>
OK,恭喜你成功了