springboot-shiro

来源:互联网 发布:2015乘用车销量数据 编辑:程序博客网 时间:2024/05/18 15:53

1.数据库设计:

主要涉及到五张表:用户表,角色表(用户所拥有的角色),权限表(角色所涉及到的权限),用户-角色表(用户和角色是多对多的),角色-权限表(角色和权限是多对多的)

DROP TABLE IF EXISTS `module`;CREATE TABLE `module` (  `mid` int(11) NOT NULL AUTO_INCREMENT,  `mname` varchar(255) DEFAULT NULL,  PRIMARY KEY (`mid`)) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;-- ------------------------------ Records of module-- ----------------------------INSERT INTO `module` VALUES ('1', 'add');INSERT INTO `module` VALUES ('2', 'delete');INSERT INTO `module` VALUES ('3', 'query');INSERT INTO `module` VALUES ('4', 'update');-- ------------------------------ Table structure for module_role-- ----------------------------DROP TABLE IF EXISTS `module_role`;CREATE TABLE `module_role` (  `rid` int(11) DEFAULT NULL,  `mid` int(11) DEFAULT NULL,  KEY `rid` (`rid`),  KEY `mid` (`mid`),  CONSTRAINT `mid` FOREIGN KEY (`mid`) REFERENCES `module` (`mid`),  CONSTRAINT `rid` FOREIGN KEY (`rid`) REFERENCES `role` (`rid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ------------------------------ Records of module_role-- ----------------------------INSERT INTO `module_role` VALUES ('1', '1');INSERT INTO `module_role` VALUES ('1', '2');INSERT INTO `module_role` VALUES ('1', '3');INSERT INTO `module_role` VALUES ('1', '4');INSERT INTO `module_role` VALUES ('2', '1');INSERT INTO `module_role` VALUES ('2', '3');-- ------------------------------ Table structure for role-- ----------------------------DROP TABLE IF EXISTS `role`;CREATE TABLE `role` (  `rid` int(11) NOT NULL AUTO_INCREMENT,  `rname` varchar(255) DEFAULT NULL,  PRIMARY KEY (`rid`)) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;-- ------------------------------ Records of role-- ----------------------------INSERT INTO `role` VALUES ('1', 'admin');INSERT INTO `role` VALUES ('2', 'customer');-- ------------------------------ Table structure for user-- ----------------------------DROP TABLE IF EXISTS `user`;CREATE TABLE `user` (  `uid` int(11) NOT NULL AUTO_INCREMENT,  `username` varchar(255) DEFAULT NULL,  `password` varchar(255) DEFAULT NULL,  PRIMARY KEY (`uid`)) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;-- ------------------------------ Records of user-- ----------------------------INSERT INTO `user` VALUES ('1', 'hlhdidi', '123');INSERT INTO `user` VALUES ('2', 'xyycici', '1992');-- ------------------------------ Table structure for user_role-- ----------------------------DROP TABLE IF EXISTS `user_role`;CREATE TABLE `user_role` (  `uid` int(11) DEFAULT NULL,  `rid` int(11) DEFAULT NULL,  KEY `u_fk` (`uid`),  KEY `r_fk` (`rid`),  CONSTRAINT `r_fk` FOREIGN KEY (`rid`) REFERENCES `role` (`rid`),  CONSTRAINT `u_fk` FOREIGN KEY (`uid`) REFERENCES `user` (`uid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;-- ------------------------------ Records of user_role-- ----------------------------INSERT INTO `user_role` VALUES ('1', '1');INSERT INTO `user_role` VALUES ('2', '2');

2.对应的实体类

public class User implements Serializable {    private Integer uid;    private String username;    private String password;    private Set<Role> roles;}
public class Role {    private Integer rid;    private String rname;    private Set<User> users ;    private Set<Module> modules;}
public class Module {    private Integer mid;    private String mname;    private Set<Role> roles;}
3.UserMapper.xml
<mapper namespace="com.wacqq.mapper.UserMapper">    <resultMap type="com.wacqq.pojo.User" id="userMap">        <id property="uid" column="uid"/>        <result property="username" column="username"/>        <result property="password" column="password"/>        <collection property="roles" ofType="com.wacqq.pojo.Role">            <id property="rid" column="rid"/>            <result property="rname" column="rname"/>            <collection property="modules" ofType="com.wacqq.pojo.Module">                <id property="mid" column="mid"/>                <result property="mname" column="mname"/>            </collection>        </collection>    </resultMap>    <select id="findByUserName" parameterType="string" resultMap="userMap">        SELECT u.*,r.*,m.* FROM user u inner join user_role ur on ur.uid=u.uid         inner join role r on r.rid=ur.rid        inner join module_role mr on mr.rid=r.rid         inner join module m on mr.mid=m.mid         WHERE username=#{username}    </select></mapper>
4.类AuthRealm完成根据用户名去数据库的查询,并且将用户信息放入shiro中,供第二个类调用

授权的方法是在碰到<shiro:hasPermission>标签的时候调用的,它会去检测shiro框架中的权限(这里的permissions)是否包含有该标签的name值,如果有,里面的内容显示,如果没有,里面的内容不予显示(这就完成了对于权限的认证.)

public class AuthRealm extends AuthorizingRealm{    @Autowired    private UserService userService;        //认证.登录    @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {        UsernamePasswordToken utoken=(UsernamePasswordToken) token;//获取用户输入的token        String username = utoken.getUsername();        User user = userService.findUserByUserName(username);        return new SimpleAuthenticationInfo(user, user.getPassword(),this.getClass().getName());//放入shiro.调用CredentialsMatcher检验密码    }    //授权    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {        User user=(User) principal.fromRealm(this.getClass().getName()).iterator().next();//获取session中的用户        List<String> permissions=new ArrayList<>();        Set<Role> roles = user.getRoles();        if(roles.size()>0) {            for(Role role : roles) {                Set<Module> modules = role.getModules();                if(modules.size()>0) {                    for(Module module : modules) {                        permissions.add(module.getMname());                    }                }            }        }        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();        info.addStringPermissions(permissions);//将权限放入shiro中.        return info;    }}

5.CredentialsMatcher,完成对于密码的校验.其中用户的信息来自shiro.

public class CredentialsMatcher extends SimpleCredentialsMatcher{    @Override    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {        UsernamePasswordToken utoken=(UsernamePasswordToken) token;        //获得用户输入的密码:(可以采用加盐(salt)的方式去检验)        String inPassword = new String(utoken.getPassword());        //获得数据库中的密码        String dbPassword=(String) info.getCredentials();        //进行密码的比对        return this.equals(inPassword, dbPassword);    }    }

6.shiro配置类

public class CredentialsMatcher extends SimpleCredentialsMatcher{    @Override    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {        UsernamePasswordToken utoken=(UsernamePasswordToken) token;        //获得用户输入的密码:(可以采用加盐(salt)的方式去检验)        String inPassword = new String(utoken.getPassword());        //获得数据库中的密码        String dbPassword=(String) info.getCredentials();        //进行密码的比对        return this.equals(inPassword, dbPassword);    }    }


7.登录页面login.jsp

<h1>欢迎登录!${user.username }</h1>    <form action="${pageContext.request.contextPath }/loginUser" method="post">        <input type="text" name="username"><br>        <input type="password" name="password"><br>        <input type="submit" value="提交">    </form>

8.用户主页index.jsp

<h1>欢迎${user.username }光临!请选择你的操作:</h1><br>    <ul>        <shiro:hasPermission name="add"><li>增加</li></shiro:hasPermission>        <shiro:hasPermission name="delete"><li>删除</li></shiro:hasPermission>        <shiro:hasPermission name="update"><li>修改</li></shiro:hasPermission>        <shiro:hasPermission name="query"><li>查询</li></shiro:hasPermission>    </ul>        <a href="${pageContext.request.contextPath }/logOut">点我注销</a>
9.LoginController测试效果:

和shiro框架的交互完全通过Subject这个类去交互,用它完成登录,注销,获取当前的用户对象等操作

@Controllerpublic class LoginController {    @RequestMapping("/login")    public String login() {        return "login";    }    @RequestMapping("/loginUser")    public String loginUser(String username,String password,HttpSession session) {        UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(username,password);        Subject subject = SecurityUtils.getSubject();        try {            subject.login(usernamePasswordToken);   //完成登录            User user=(User) subject.getPrincipal();            session.setAttribute("user", user);            return "index";        } catch(Exception e) {            return "login";//返回登录页面        }            }    @RequestMapping("/logOut")    public String logOut(HttpSession session) {        Subject subject = SecurityUtils.getSubject();        subject.logout();//        session.removeAttribute("user");        return "login";    }}




特别鸣谢: http://www.cnblogs.com/hlhdidi/p/6376457.html

原创粉丝点击