SSM + Shiro 整合(4)- 在 Web 项目中添加 Shiro

来源:互联网 发布:盛发软件 编辑:程序博客网 时间:2024/05/21 21:47

项目源码:https://github.com/weimingge14/Shiro-project
演示地址:http://liweiblog.duapp.com/Shiro-project/login

SSM + Shiro 整合 (4)- 在 Web 项目中添加 Shiro

本节的目标是整合 Shiro。

步骤1:添加依赖

<dependency>    <groupId>org.apache.shiro</groupId>    <artifactId>shiro-core</artifactId>    <version>${shiro.version}</version></dependency><dependency>    <groupId>org.apache.shiro</groupId>    <artifactId>shiro-web</artifactId>    <version>${shiro.version}</version></dependency>

步骤2:添加配置文件 shiro.ini

(说明:下面的这个配置是全部写好的配置,请大家要明白每一行配置的意思,一点一点添加完成功能上的测试)

[main]# 声明一个密码匹配器credentialsMatcher = org.apache.shiro.authc.credential.HashedCredentialsMatcher# 设置该密码匹配器使用的算法是 md5credentialsMatcher.hashAlgorithmName=md5# 声明一个自定义的 Realm myRealm = com.liwei.shiro.realm.MyRealm# 将上面声明的密码匹配器注入到自定义 Realm 的属性中去myRealm.credentialsMatcher=$credentialsMatcher# 自定义一个权限匹配器permissionResolver=com.liwei.shiro.permission.UrlPermissionResolver# 将自定义的权限匹配器注入到自定义 Realm 中myRealm.permissionResolver = $permissionResolver# 设置安全管理器的安全数据源为自定义的 RealmsecurityManager.realms=$myRealm# 如果认证不通过,浏览器通过 Get 方式请求到 /login 上authc.loginUrl=/login[filters]# 声明一个自定义的过滤器resourceCheckFilter = com.liwei.shiro.filter.ResourceCheckFilter# 为上面声明的自定义过滤器注入属性值resourceCheckFilter.errorUrl=/unAuthorization[urls]# 配置 url 与使用的过滤器之间的关系/admin/**=authc,resourceCheckFilter/login=anon

总结:在没有使用 Spring 整合 Shiro 的时候,我们在 web.xml 里面配置监听器和过滤器。整合 Spring 的时候,我们应该在 web.xml 里面配置一个代理。
单纯的 web 应用使用的是 shiro.int 来实例化 Shiro 的各个组件,如果我们使用 Spring 的话,就要使用 Spring 的 Bean 文件了,这样 shiro.ini 文件就要转换成 Spring 的 Bean 文件。

配置与 Spring 的整合,就要添加 Spring 的依赖。

<dependency>    <groupId>org.apache.shiro</groupId>    <artifactId>shiro-spring</artifactId>    <version>${shiro.version}</version></dependency>

步骤3:在 web.xml 中添加

<!-- 添加 Shiro 相关配置 --><listener>    <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class></listener><filter>    <filter-name>ShiroFilter</filter-name>    <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class></filter><filter-mapping>    <filter-name>ShiroFilter</filter-name>    <url-pattern>/*</url-pattern>    <dispatcher>REQUEST</dispatcher>    <dispatcher>FORWARD</dispatcher>    <dispatcher>INCLUDE</dispatcher>    <dispatcher>ERROR</dispatcher></filter-mapping>

步骤4:编写自定义 Realm

public class MyRealm extends AuthorizingRealm {    @Autowired    private IUserService userService;    private static final Logger logger = LoggerFactory.getLogger(MyRealm.class);    /**     * 授权     * @param principalCollection     * @return     */    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {        logger.info("--- MyRealm doGetAuthorizationInfo ---");        // 获得经过认证的主体信息        User user = (User)principalCollection.getPrimaryPrincipal();        Integer userId = user.getId();        // UserService userService = (UserService)InitServlet.getBean("userService");        List<Resource> resourceList = userService.listAllResource(userId);        List<String> roleSnList = userService.listRoleSnByUser(userId);        List<String> resStrList = new ArrayList<>();        for(Resource resource:resourceList){            resStrList.add(resource.getUrl());        }        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();        info.setRoles(new HashSet<>(roleSnList));        info.setStringPermissions(new HashSet<>(resStrList));        // 以上完成了动态地对用户授权        logger.debug("role => " + roleSnList);        logger.debug("permission => " + resStrList);        return info;    }    /**     * 认证     * @param authenticationToken     * @return     * @throws AuthenticationException     */    @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {        logger.info("--- MyRealm doGetAuthenticationInfo ---");        String username = authenticationToken.getPrincipal().toString();        // String password = new String((char[])authenticationToken.getCredentials());        // 以后我们使用 Spring 管理 Shiro 的时候,就不必要这样得到 UserService 了        // userService = (IUserService) InitServlet.getBean("userService");        // User user = userService.login(username,password);        // 这里应该使用 load 方法,比对用户名的密码的环节应该交给 Shiro 这个框架去完成        User user = userService.loadByUsername(username);        // 第 1 个参数可以传一个实体对象,然后在认证的环节可以取出        // 第 2 个参数应该传递在数据库中“正确”的数据,然后和 token 中的数据进行匹配        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),getName());        // 设置盐值        info.setCredentialsSalt(ByteSource.Util.bytes(username.getBytes()));        return info;    }}

步骤5:编写登录的方法

@RequestMapping(value = "/")@Controllerpublic class LoginController {    private static final Logger logger = LoggerFactory.getLogger(LoginController.class);    @RequestMapping(value = "/login",method = RequestMethod.GET)    public String login(){        return "login";    }    @RequestMapping(value = "/login",method = RequestMethod.POST)    public String login(User user, Model model){        String username = user.getUsername();        String password = user.getPassword();        logger.debug("username => " + username);        logger.debug("password => " + password);        UsernamePasswordToken token = new UsernamePasswordToken(username,password);        Subject subject = SecurityUtils.getSubject();        String msg = null;        try {            subject.login(token);        } catch (UnknownAccountException e) {            e.printStackTrace();            msg = e.getMessage();        } catch (IncorrectCredentialsException e){            e.printStackTrace();            msg = e.getMessage();        }        if(msg == null){            return "redirect:/admin/user/list";        }        model.addAttribute("msg",msg);        return "login";    }    @RequestMapping(value = "/logout",method = RequestMethod.GET)    public String logout(Model model){        Subject subject = SecurityUtils.getSubject();        subject.logout();        model.addAttribute("msg","您已经退出登录");        return "login";    }    @RequestMapping(value = "/unAuthorization")    public String unAuthorization(){        return "unAuthorization";    }}
0 0
原创粉丝点击