这里不对shiro做详细介绍,仅仅是做一个基本功能可以用的例子供大家参考,网上例子大多详细,不能实现。

1创建4张表:

desc tb_user;
+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| id         | int(11)     | NO   | PRI | NULL    | auto_increment |
| username   | varchar(55) | YES  |     | NULL    |                |
| password   | varchar(55) | YES  |     | NULL    |                |
| isDelete   | tinyint(1)  | YES  |     | NULL    |                |
| createDate | date        | YES  |     | NULL    |                |
+------------+-------------+------+-----+---------+----------------+

desc role;
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| name        | varchar(55)  | YES  |     | NULL    |                |
| description | varchar(255) | YES  |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+
desc tb_user;
+------------+-------------+------+-----+---------+----------------+
| Field      | Type        | Null | Key | Default | Extra          |
+------------+-------------+------+-----+---------+----------------+
| id         | int(11)     | NO   | PRI | NULL    | auto_increment |
| username   | varchar(55) | YES  |     | NULL    |                |
| password   | varchar(55) | YES  |     | NULL    |                |
| isDelete   | tinyint(1)  | YES  |     | NULL    |                |
| createDate | date        | YES  |     | NULL    |                |
+------------+-------------+------+-----+---------+----------------+

 desc permission;
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| token       | varchar(55)  | YES  |     | NULL    |                |
| theurl      | varchar(55)  | YES  |     | NULL    |                |
| description | varchar(255) | YES  |     | NULL    |                |
| roleId      | int(11)      | YES  | MUL | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+

表没看懂的看实体类吧

2建立实体类:

用户:

/**
* 用户
*/
public class User {
private int id;
private String username;
private String password;
private boolean isDelete;
private Date createDate;
List<Role> userRoles;

角色:

/**
* 角色表
*/
public class Role {
private int id;
private String name;
private String description;

权限:

/**
* 权限表
*/
public class Permission {
private int id;
private String token;
private String theurl;
private String description;
private int roleId;

3数据查询

shiro的原理是根据用户登录名去查找他是否有响应角色或者相应权利,然后角色和权利才是决定访问权限的

@Repository
public interface PermissionMapper {
/**
* 查询一个角色的所有权限
* @param roleId
* @return
*/
@Select("select * from permission where roleId=#{roleId}")
@Results({
@Result(id=true,column = "id",property = "id"),
@Result(column = "token",property = "token"),
@Result(column = "theurl",property = "theurl"),
@Result(column = "description",property = "description"),
@Result(column = "roleId",property = "roleId")
})
List<Permission> selectPermissionByRoleId(@Param("roleId") int roleId);
}
@Repository
public interface RoleMapper {
/**
* 查询一个用户的所有角色
* @param userid
* @return
*/
@Select("select * from role where id in (select roleid from userrole where userid=#{userid})")
@Results({
@Result(id=true,column = "id",property = "id"),
@Result(column = "name",property = "name"),
@Result(column = "description",property = "description")
})
List<Role> selectByUserId(@Param("userid") int userid);
}
@Repository
public interface UserMapper {
/**
* 根据用户名查询用户的所有信息
* @param username
* @return
*/
@Select("select * from tb_user where username=#{username}")
@Results({
@Result(id = true,column = "id",property = "id"),
@Result(column = "username",property = "username"),
@Result(column = "password",property = "password"),
@Result(column = "isDelete",property = "isDelete"),
@Result(column = "createDate",property = "createDate"),
@Result(column = "id",property = "userRoles",
many = @Many(select="com.smart.dao.RoleMapper.selectByUserId",fetchType = FetchType.LAZY))
})
User selectUserByName(@Param("username") String username);
}

4服务层设计具体需要的信息,只给接口,代码的话,我会给源码:

public interface PermissionService {
/**
* 根据用户id找出该用户所有权限
* @param userid
* @return
*/
List<Permission> getPermissionByUserId(int userid);

/**
* 根据用户名字,找出所有权限字段
* @param username
* @return
*/
List<String> getTheUrl(String username);
}
public interface RoleService {
/**
* 根据用户id找出用户所有角色
* @param userid
* @return
*/
List<Role> getRoles(int userid);
}
public interface UserService {
User getUserByUsername(String username);
}
5自定义AuthorizingRealm
@Component("myshiroReam")
public class MyShiroRealm extends AuthorizingRealm {
@Autowired
@Qualifier("permissionService")
private PermissionService permissionService;
@Autowired
@Qualifier("userService")
private UserService userService;
@Autowired
@Qualifier("roleService")
private RoleService roleService;
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取登录时输入的用户名
String username=(String) principalCollection.fromRealm(getName()).iterator().next();
if(username!=null){
List<String> listUrl=permissionService.getTheUrl(username);//权限
User user=userService.getUserByUsername(username);//用户信息
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
if(listUrl!=null&&!listUrl.isEmpty()){
for(String url:listUrl){
info.addStringPermission(url);//加入权限
}
}
List<Role> roles=roleService.getRoles(user.getId());
if(roles!=null&&!roles.isEmpty()){
for(Role role:roles){
info.addRole(role.getName());//加入角色
}
}
return info;
}
return null;
}

protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token=(UsernamePasswordToken)authenticationToken;
//通过表单接收的用户名
String username=token.getUsername();
if(username!=null&&!"".equals(username)){
User user=userService.getUserByUsername(username);
if(user!=null){
return new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),getName());
}
}
return null;
}
}
6配置过滤器web.xml中:
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>7配置spring配置文件:
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/toLogin"/><!--登录页面,-->
<property name="successUrl" value="/success"/><!--登录成功页面,如果自己设置了返回页面,则不跳转-->
<property name="unauthorizedUrl" value="/error"/>
<property name="filterChainDefinitions">
<value>
/toLogin=anon <!--表示都可以访问-->
/login=anon
/home=perms[home] <!--perms表示需要该权限才能访问的页面-->
/admin=roles["admin,user"] <!--只有拥有admin角色的用户才可访问,同时需要拥有多个角色的话,用引号引起来,中间用逗号隔开-->
/**=authc <!--authc表示需要认证才能访问的页面-->
</value>
</property>
</bean>
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myshiroReam"/>
</bean>8控制器中设置测试:
@Controller
public class LoginController {
@Autowired
@Qualifier("userService")
private UserService userService;
//跳转到登录页面
@RequestMapping(value = "/toLogin")
public String toLogin(){
return "login";
}
//实现用户登录
@RequestMapping(value = "/login")
public ModelAndView Login(String username,String password){
ModelAndView mav=new ModelAndView();
User user=userService.getUserByUsername(username);
if(user==null){
mav.setViewName("toLogin");
mav.addObject("msg","用户不存在");
}
if(!user.getPassword().equals(password)){
mav.setViewName("toLogin");
mav.addObject("msg","账号密码错误");
return mav;
}
SecurityUtils.getSecurityManager().logout(SecurityUtils.getSubject());//如果原来有的话,就退出
//登录后存放进shiro token
UsernamePasswordToken token=new UsernamePasswordToken(user.getUsername(),user.getPassword());
Subject subject=SecurityUtils.getSubject();
subject.login(token);
//登录成功后会跳转到successUrl配置的链接,不用管下面返回的链接
mav.setViewName("redirect:/success");
return mav;
}
@RequestMapping(value = "logout")
public String logout(){
SecurityUtils.getSecurityManager().logout(SecurityUtils.getSubject());//退出
return "login";
}
}
@Controller
public class IndexController {
@RequestMapping("/home")
public String index(){
System.out.println("登录成功");
return "home";
}
@RequestMapping("/success")
public String success(){
return "success";
}
@RequestMapping("/error")
public String error(){
return "error";
}
@RequestMapping("/admin")
public String admin(){
return "admin";
}
}
前台页面不写了,具体代码:
https://github.com/zhanxupeng/shiro