Shiro框架集成Spring(从mysql到web)

Shiro集成Spring详细步骤

1.导包

为了方便直接导入Shiro所有的jar包

<dependency>
      <groupId>org.apache.shiro</groupId>
      <artifactId>shiro-all</artifactId>
      <version>1.2.3</version>
</dependency>

2.在web.xml文件配置Shiro拦截器

<!--配置Shiro过滤器-->
    <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>  <!--让shiro拦截所有请求-->
    </filter-mapping>

3.配置Shiro配置文件

1.配置过滤器
bean的id名要和filter-name名字一样
默认:
anon 放行
authc 拦截

<!--配置过滤器-->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManage"/>
        <property name="loginUrl" value="index.jsp"/>  <!--配置登录页面-->
        <property name="unauthorizedUrl" value="404.jsp"/> <!--配置不需要认证的页面-->
        <!--配置过滤链-->
        <property name="filterChainDefinitions">
            <value>
                /index.jsp = anon <!--放行-->
                /login = anon <!--这里是Controller里登录方法的url也要放行-->
                /* =  authc <!--拦截-->
            </value>
        </property>
    </bean>

2.配置shiro核心对象SecurityManage
注意是导包是DefaultWebSecurityManager,不是DefaultSecurityManager 。如果导包导错web端会报错

<!--配置安全管理员-->
    <bean id="securityManage" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="realm"/>  
    </bean>

3.配置自定义realm

 <!--配置自定义Realm-->
    <bean id="realm" class="com.hwua.util.CustomRealm">
        <property name="credentialsMatcher" ref="credentialsMatcher"></property>
    </bean>

4.配置加密算法

<!--配置加密算法-->
    <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher" id="credentialsMatcher">
        <property name="hashAlgorithmName" value="md5"></property> <!--使用md5算法-->
        <property name="hashIterations" value="1"></property> <!--次数1次-->
    </bean>

4.数据库表的关系

首先先看下数据库三张表中的关系
第一张表用户表:用户ID、用户账户、用户密码
在这里插入图片描述
第二张表角色表:角色id、用户名/用户id、角色名
在这里插入图片描述
第三表权限表:权限id、角色名、角色的权限
在这里插入图片描述
三张表的关系是:通过用户名—>找到角色定位,再通过角色定位——>找到对应的权限,通过权限可以展示指定的菜单

5.编写Mapper层和Service层

Mapper层

@Mapper
public interface UsersMapper {

    /**
     * 通过用户名查找用户信息
     * @param name
     * @return
     */
    @Select({"select * from users where username = #{name}"})
    public abstract Users finUserByName(@Param("name") String name);

    /**
     * 通过用户名查找角色
     * @param name
     * @return
     */
    @Select("select id,username,role_name as roleName from user_role where username = #{name}")
    public abstract List<UserRole> findRoleByUNAME(String name);

    /**
     * 通过用户名查找角色的权限
     * @param rName
     * @return
     */
    @Select("select * from role_permission where role_name = #{rName}")
    public abstract List<RolePermission> findPermissionByRName(String rName);
}

Service层

@Service
public class UserService {


    @Autowired
    UsersMapper usersMapper;

    /**
     * 根据用户名查询user
     * @param name
     * @return
     */
    public Users UserByName(String name){

        return usersMapper.finUserByName(name);
    }

    /**
     * 根据用户名查询角色定位
     * @param name
     * @return
     */
    public Set<String> RoleByName(String name){
        List<UserRole> roles = usersMapper.findRoleByUNAME(name);
        Set<String> set = new HashSet<String>();
        for (UserRole role : roles) {
            set.add(role.getRoleName());
        }
        return set;
    }

    /**
     * 根据角色名查询可访问的资源
     * @param name
     * @return
     */
    public Set<String> permissionByRName(String name){
        //通过username查询到角色定位结果集
        Set<String> roleName = RoleByName(name);
        Set<String> set = new HashSet<String>();
        for (String role : roleName) {
            //通过角色查到对应的权限对象
            List<RolePermission> rpList = usersMapper.findPermissionByRName(role);
            //把权限结果集进行提取封装
            for (RolePermission permission : rpList) {
                set.add(permission.getPermission());
            }
        }
        return set;
    }
}

6.编写自定义的Realm

//自定义Realm
public class CustomRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;


    /**
     * 权限管理
     * @param principalCollection
     * @return
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取主体的用户名
        String username = (String)principalCollection.getPrimaryPrincipal();
        //创建simpleAuthorizationInfo对象作为返回值
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //查询角色
        Set<String> roles = userService.RoleByName(username);
        //查询权限
        Set<String> permissions = userService.permissionByRName(username);
        simpleAuthorizationInfo.setStringPermissions(permissions);
        simpleAuthorizationInfo.setRoles(roles);
        return simpleAuthorizationInfo;
    }

    /**
     * 认证管理
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        //通过主体传过来的获取username
        String username = (String)authenticationToken.getPrincipal();
        //通过用户名获取password
        Users users = userService.UserByName(username);
        if (users==null){
            return null;
        }

        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username,users.getPassword(),"customRealm");
        //返回的值加上盐
        simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes("abc"));
        return simpleAuthenticationInfo;
    }


}

7.编写Controller层

@Controller
public class UserController {

    @RequestMapping(value = "/login",method = RequestMethod.GET)
    public String login(Users users){
        //获得主体
        Subject subject = SecurityUtils.getSubject();
        //创建Token
        UsernamePasswordToken token = new UsernamePasswordToken(users.getUsername(),users.getPassword());
        //判断是否认证成功
        try {
            subject.login(token);
        }catch (Exception e){
            return "404";
        }
        //判断是否有admin权限
        if (subject.hasRole("admin")){
            System.out.println("admin");
            return "admin";
        }
        return "success";
    }
}

8.最终效果

张三有admin权限进行登录
在这里插入图片描述
在这里插入图片描述

王五没有admin权限
在这里插入图片描述
在这里插入图片描述

第一次写博客,如果技术当中有错误的地方欢迎指出,不喜勿喷,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值